Blame view

fs/cifs/connect.c 104 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
  /*
   *   fs/cifs/connect.c
   *
d185cda77   Steve French   [CIFS] rename cif...
4
   *   Copyright (C) International Business Machines  Corp., 2002,2009
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5
6
7
8
9
10
11
12
13
14
15
16
17
18
   *   Author(s): Steve French (sfrench@us.ibm.com)
   *
   *   This library is free software; you can redistribute it and/or modify
   *   it under the terms of the GNU Lesser General Public License as published
   *   by the Free Software Foundation; either version 2.1 of the License, or
   *   (at your option) any later version.
   *
   *   This library is distributed in the hope that it will be useful,
   *   but WITHOUT ANY WARRANTY; without even the implied warranty of
   *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
   *   the GNU Lesser General Public License for more details.
   *
   *   You should have received a copy of the GNU Lesser General Public License
   *   along with this library; if not, write to the Free Software
fb8c4b14d   Steve French   [CIFS] whitespace...
19
   *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
20
21
22
23
24
25
   */
  #include <linux/fs.h>
  #include <linux/net.h>
  #include <linux/string.h>
  #include <linux/list.h>
  #include <linux/wait.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
26
  #include <linux/slab.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
27
28
29
30
  #include <linux/pagemap.h>
  #include <linux/ctype.h>
  #include <linux/utsname.h>
  #include <linux/mempool.h>
b8643e1b5   Steve French   [PATCH] cifs: Do ...
31
  #include <linux/delay.h>
f191401f5   Steve French   [CIFS] rmmod cifs...
32
  #include <linux/completion.h>
aaf737adb   Igor Mammedov   [CIFS] Switch cif...
33
  #include <linux/kthread.h>
0ae0efada   Steve French   [CIFS] Fix rsize ...
34
  #include <linux/pagevec.h>
7dfb71030   Nigel Cunningham   [PATCH] Add inclu...
35
  #include <linux/freezer.h>
5c2503a8e   Igor Mammedov   Added loop check ...
36
  #include <linux/namei.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
37
38
  #include <asm/uaccess.h>
  #include <asm/processor.h>
50b64e3b7   Jeff Layton   cifs: fix IPv6 ad...
39
  #include <linux/inet.h>
0e2bedaa3   Steve French   [CIFS] ipv6_addr_...
40
  #include <net/ipv6.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
41
42
43
44
45
46
47
48
49
  #include "cifspdu.h"
  #include "cifsglob.h"
  #include "cifsproto.h"
  #include "cifs_unicode.h"
  #include "cifs_debug.h"
  #include "cifs_fs_sb.h"
  #include "ntlmssp.h"
  #include "nterr.h"
  #include "rfc1002pdu.h"
488f1d2d6   Suresh Jayaraman   cifs: define serv...
50
  #include "fscache.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
51
52
53
  
  #define CIFS_PORT 445
  #define RFC1001_PORT 139
c74093b69   Jeff Layton   cifs: set up recu...
54
55
  /* SMB echo "timeout" -- FIXME: tunable? */
  #define SMB_ECHO_INTERVAL (60 * HZ)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
56
  extern mempool_t *cifs_req_poolp;
2de970ff6   Jeff Layton   cifs: implement r...
57
  /* FIXME: should these be tunable? */
9d002df49   Jeff Layton   cifs: add routine...
58
  #define TLINK_ERROR_EXPIRE	(1 * HZ)
2de970ff6   Jeff Layton   cifs: implement r...
59
  #define TLINK_IDLE_EXPIRE	(600 * HZ)
9d002df49   Jeff Layton   cifs: add routine...
60

a9f1b85e5   Pavel Shilovsky   CIFS: Simplify ip...
61
62
  static int ip_connect(struct TCP_Server_Info *server);
  static int generic_ip_connect(struct TCP_Server_Info *server);
b647c35f7   Jeff Layton   cifs: convert tli...
63
  static void tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink);
2de970ff6   Jeff Layton   cifs: implement r...
64
  static void cifs_prune_tlinks(struct work_struct *work);
b9bce2e9f   Jeff Layton   cifs: fix expand_...
65
66
  static int cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data,
  					const char *devname);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
67

d5c5605c2   Jeff Layton   cifs: make ipv6_c...
68
69
70
71
72
73
74
75
  /*
   * cifs tcp session reconnection
   *
   * mark tcp session as reconnecting so temporarily locked
   * mark all smb sessions as reconnecting for tcp session
   * reconnect tcp session
   * wake up waiters on reconnection? - (not needed currently)
   */
2cd646a2d   Steve French   [CIFS] Remove sta...
76
  static int
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
77
78
79
  cifs_reconnect(struct TCP_Server_Info *server)
  {
  	int rc = 0;
f1987b44f   Jeff Layton   cifs: reinstate s...
80
  	struct list_head *tmp, *tmp2;
96daf2b09   Steve French   [CIFS] Rename thr...
81
82
  	struct cifs_ses *ses;
  	struct cifs_tcon *tcon;
fb8c4b14d   Steve French   [CIFS] whitespace...
83
  	struct mid_q_entry *mid_entry;
3c1105df6   Jeff Layton   cifs: don't call ...
84
  	struct list_head retry_list;
50c2f7538   Steve French   [CIFS] whitespace...
85

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
86
  	spin_lock(&GlobalMid_Lock);
469ee614a   Jeff Layton   [CIFS] eliminate ...
87
  	if (server->tcpStatus == CifsExiting) {
fb8c4b14d   Steve French   [CIFS] whitespace...
88
  		/* the demux thread will exit normally
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
89
90
91
92
93
94
95
  		next time through the loop */
  		spin_unlock(&GlobalMid_Lock);
  		return rc;
  	} else
  		server->tcpStatus = CifsNeedReconnect;
  	spin_unlock(&GlobalMid_Lock);
  	server->maxBuf = 0;
b6b38f704   Joe Perches   [CIFS] Neaten cER...
96
  	cFYI(1, "Reconnecting tcp session");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
97
98
99
  
  	/* before reconnecting the tcp session, mark the smb session (uid)
  		and the tid bad so they are not used until reconnected */
2b84a36c5   Jeff Layton   cifs: allow for d...
100
  	cFYI(1, "%s: marking sessions and tcons for reconnect", __func__);
3f9bcca78   Suresh Jayaraman   cifs: convert cif...
101
  	spin_lock(&cifs_tcp_ses_lock);
14fbf50d6   Jeff Layton   cifs: reinstate s...
102
  	list_for_each(tmp, &server->smb_ses_list) {
96daf2b09   Steve French   [CIFS] Rename thr...
103
  		ses = list_entry(tmp, struct cifs_ses, smb_ses_list);
14fbf50d6   Jeff Layton   cifs: reinstate s...
104
105
  		ses->need_reconnect = true;
  		ses->ipc_tid = 0;
f1987b44f   Jeff Layton   cifs: reinstate s...
106
  		list_for_each(tmp2, &ses->tcon_list) {
96daf2b09   Steve French   [CIFS] Rename thr...
107
  			tcon = list_entry(tmp2, struct cifs_tcon, tcon_list);
3b7952109   Steve French   [CIFS] Fix cifs r...
108
  			tcon->need_reconnect = true;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
109
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
110
  	}
3f9bcca78   Suresh Jayaraman   cifs: convert cif...
111
  	spin_unlock(&cifs_tcp_ses_lock);
2b84a36c5   Jeff Layton   cifs: allow for d...
112

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
113
  	/* do not want to be sending data on a socket we are freeing */
2b84a36c5   Jeff Layton   cifs: allow for d...
114
  	cFYI(1, "%s: tearing down socket", __func__);
72ca545b2   Jeff Layton   cifs: convert tcp...
115
  	mutex_lock(&server->srv_mutex);
fb8c4b14d   Steve French   [CIFS] whitespace...
116
  	if (server->ssocket) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
117
118
  		cFYI(1, "State: 0x%x Flags: 0x%lx", server->ssocket->state,
  			server->ssocket->flags);
91cf45f02   Trond Myklebust   [NET]: Add the he...
119
  		kernel_sock_shutdown(server->ssocket, SHUT_WR);
b6b38f704   Joe Perches   [CIFS] Neaten cER...
120
  		cFYI(1, "Post shutdown state: 0x%x Flags: 0x%lx",
467a8f8d4   Steve French   [CIFS] whitespace...
121
  			server->ssocket->state,
b6b38f704   Joe Perches   [CIFS] Neaten cER...
122
  			server->ssocket->flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
123
124
125
  		sock_release(server->ssocket);
  		server->ssocket = NULL;
  	}
5d0d28824   Shirish Pargaonkar   NTLM authenticati...
126
127
  	server->sequence_number = 0;
  	server->session_estab = false;
21e733930   Shirish Pargaonkar   NTLM auth and sig...
128
129
130
  	kfree(server->session_key.response);
  	server->session_key.response = NULL;
  	server->session_key.len = 0;
fda359436   Steve French   [CIFS] cifs: reco...
131
  	server->lstrp = jiffies;
2b84a36c5   Jeff Layton   cifs: allow for d...
132
  	mutex_unlock(&server->srv_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
133

2b84a36c5   Jeff Layton   cifs: allow for d...
134
  	/* mark submitted MIDs for retry and issue callback */
3c1105df6   Jeff Layton   cifs: don't call ...
135
136
  	INIT_LIST_HEAD(&retry_list);
  	cFYI(1, "%s: moving mids to private list", __func__);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
137
  	spin_lock(&GlobalMid_Lock);
2b84a36c5   Jeff Layton   cifs: allow for d...
138
139
140
  	list_for_each_safe(tmp, tmp2, &server->pending_mid_q) {
  		mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
  		if (mid_entry->midState == MID_REQUEST_SUBMITTED)
ad8b15f0f   Steve French   [CIFS] list entry...
141
  			mid_entry->midState = MID_RETRY_NEEDED;
3c1105df6   Jeff Layton   cifs: don't call ...
142
143
144
145
146
147
148
  		list_move(&mid_entry->qhead, &retry_list);
  	}
  	spin_unlock(&GlobalMid_Lock);
  
  	cFYI(1, "%s: issuing mid callbacks", __func__);
  	list_for_each_safe(tmp, tmp2, &retry_list) {
  		mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
2b84a36c5   Jeff Layton   cifs: allow for d...
149
150
  		list_del_init(&mid_entry->qhead);
  		mid_entry->callback(mid_entry);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
151
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
152

7fdbaa1b8   Jeff Layton   cifs: don't allow...
153
  	do {
6c3d8909d   Steve French   [CIFS] Allow cifs...
154
  		try_to_freeze();
a9f1b85e5   Pavel Shilovsky   CIFS: Simplify ip...
155
156
157
  
  		/* we should try only the port we connected to before */
  		rc = generic_ip_connect(server);
fb8c4b14d   Steve French   [CIFS] whitespace...
158
  		if (rc) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
159
  			cFYI(1, "reconnect error %d", rc);
0cb766ae6   Steve French   [PATCH] cifs: Do ...
160
  			msleep(3000);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
161
162
163
  		} else {
  			atomic_inc(&tcpSesReconnectCount);
  			spin_lock(&GlobalMid_Lock);
469ee614a   Jeff Layton   [CIFS] eliminate ...
164
  			if (server->tcpStatus != CifsExiting)
fd88ce931   Steve French   [CIFS] cifs: clar...
165
  				server->tcpStatus = CifsNeedNegotiate;
fb8c4b14d   Steve French   [CIFS] whitespace...
166
  			spin_unlock(&GlobalMid_Lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
167
  		}
7fdbaa1b8   Jeff Layton   cifs: don't allow...
168
  	} while (server->tcpStatus == CifsNeedReconnect);
2b84a36c5   Jeff Layton   cifs: allow for d...
169

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
170
171
  	return rc;
  }
fb8c4b14d   Steve French   [CIFS] whitespace...
172
  /*
e4eb295d3   Steve French   [PATCH] cifs: Han...
173
174
175
176
177
178
  	return codes:
  		0 	not a transact2, or all data present
  		>0 	transact2 with that much data missing
  		-EINVAL = invalid transact2
  
   */
fb8c4b14d   Steve French   [CIFS] whitespace...
179
  static int check2ndT2(struct smb_hdr *pSMB, unsigned int maxBufSize)
e4eb295d3   Steve French   [PATCH] cifs: Han...
180
  {
fb8c4b14d   Steve French   [CIFS] whitespace...
181
  	struct smb_t2_rsp *pSMBt;
e4eb295d3   Steve French   [PATCH] cifs: Han...
182
  	int remaining;
26ec25486   Jeff Layton   cifs: fix unalign...
183
  	__u16 total_data_size, data_in_this_rsp;
e4eb295d3   Steve French   [PATCH] cifs: Han...
184

fb8c4b14d   Steve French   [CIFS] whitespace...
185
  	if (pSMB->Command != SMB_COM_TRANSACTION2)
e4eb295d3   Steve French   [PATCH] cifs: Han...
186
  		return 0;
fb8c4b14d   Steve French   [CIFS] whitespace...
187
188
189
  	/* check for plausible wct, bcc and t2 data and parm sizes */
  	/* check for parm and data offset going beyond end of smb */
  	if (pSMB->WordCount != 10) { /* coalesce_t2 depends on this */
b6b38f704   Joe Perches   [CIFS] Neaten cER...
190
  		cFYI(1, "invalid transact2 word count");
e4eb295d3   Steve French   [PATCH] cifs: Han...
191
192
193
194
  		return -EINVAL;
  	}
  
  	pSMBt = (struct smb_t2_rsp *)pSMB;
26ec25486   Jeff Layton   cifs: fix unalign...
195
196
  	total_data_size = get_unaligned_le16(&pSMBt->t2_rsp.TotalDataCount);
  	data_in_this_rsp = get_unaligned_le16(&pSMBt->t2_rsp.DataCount);
e4eb295d3   Steve French   [PATCH] cifs: Han...
197

c0c7b905e   Jeff Layton   cifs: clean up le...
198
  	if (total_data_size == data_in_this_rsp)
e4eb295d3   Steve French   [PATCH] cifs: Han...
199
  		return 0;
c0c7b905e   Jeff Layton   cifs: clean up le...
200
  	else if (total_data_size < data_in_this_rsp) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
201
202
  		cFYI(1, "total data %d smaller than data in frame %d",
  			total_data_size, data_in_this_rsp);
e4eb295d3   Steve French   [PATCH] cifs: Han...
203
  		return -EINVAL;
e4eb295d3   Steve French   [PATCH] cifs: Han...
204
  	}
c0c7b905e   Jeff Layton   cifs: clean up le...
205
206
207
208
209
210
211
212
213
214
215
  
  	remaining = total_data_size - data_in_this_rsp;
  
  	cFYI(1, "missing %d bytes from transact2, check next response",
  		remaining);
  	if (total_data_size > maxBufSize) {
  		cERROR(1, "TotalDataSize %d is over maximum buffer %d",
  			total_data_size, maxBufSize);
  		return -EINVAL;
  	}
  	return remaining;
e4eb295d3   Steve French   [PATCH] cifs: Han...
216
  }
fb8c4b14d   Steve French   [CIFS] whitespace...
217
  static int coalesce_t2(struct smb_hdr *psecond, struct smb_hdr *pTargetSMB)
e4eb295d3   Steve French   [PATCH] cifs: Han...
218
219
220
  {
  	struct smb_t2_rsp *pSMB2 = (struct smb_t2_rsp *)psecond;
  	struct smb_t2_rsp *pSMBt  = (struct smb_t2_rsp *)pTargetSMB;
fb8c4b14d   Steve French   [CIFS] whitespace...
221
222
  	char *data_area_of_target;
  	char *data_area_of_buf2;
26ec25486   Jeff Layton   cifs: fix unalign...
223
  	int remaining;
2a2047bc9   Jeff Layton   cifs: sanitize le...
224
225
  	unsigned int byte_count, total_in_buf;
  	__u16 total_data_size, total_in_buf2;
e4eb295d3   Steve French   [PATCH] cifs: Han...
226

26ec25486   Jeff Layton   cifs: fix unalign...
227
  	total_data_size = get_unaligned_le16(&pSMBt->t2_rsp.TotalDataCount);
e4eb295d3   Steve French   [PATCH] cifs: Han...
228

26ec25486   Jeff Layton   cifs: fix unalign...
229
230
  	if (total_data_size !=
  	    get_unaligned_le16(&pSMB2->t2_rsp.TotalDataCount))
b6b38f704   Joe Perches   [CIFS] Neaten cER...
231
  		cFYI(1, "total data size of primary and secondary t2 differ");
e4eb295d3   Steve French   [PATCH] cifs: Han...
232

26ec25486   Jeff Layton   cifs: fix unalign...
233
  	total_in_buf = get_unaligned_le16(&pSMBt->t2_rsp.DataCount);
e4eb295d3   Steve French   [PATCH] cifs: Han...
234
235
  
  	remaining = total_data_size - total_in_buf;
50c2f7538   Steve French   [CIFS] whitespace...
236

fb8c4b14d   Steve French   [CIFS] whitespace...
237
  	if (remaining < 0)
2a2047bc9   Jeff Layton   cifs: sanitize le...
238
  		return -EPROTO;
e4eb295d3   Steve French   [PATCH] cifs: Han...
239

fb8c4b14d   Steve French   [CIFS] whitespace...
240
  	if (remaining == 0) /* nothing to do, ignore */
e4eb295d3   Steve French   [PATCH] cifs: Han...
241
  		return 0;
50c2f7538   Steve French   [CIFS] whitespace...
242

26ec25486   Jeff Layton   cifs: fix unalign...
243
  	total_in_buf2 = get_unaligned_le16(&pSMB2->t2_rsp.DataCount);
fb8c4b14d   Steve French   [CIFS] whitespace...
244
  	if (remaining < total_in_buf2) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
245
  		cFYI(1, "transact2 2nd response contains too much data");
e4eb295d3   Steve French   [PATCH] cifs: Han...
246
247
248
  	}
  
  	/* find end of first SMB data area */
fb8c4b14d   Steve French   [CIFS] whitespace...
249
  	data_area_of_target = (char *)&pSMBt->hdr.Protocol +
26ec25486   Jeff Layton   cifs: fix unalign...
250
  				get_unaligned_le16(&pSMBt->t2_rsp.DataOffset);
e4eb295d3   Steve French   [PATCH] cifs: Han...
251
  	/* validate target area */
26ec25486   Jeff Layton   cifs: fix unalign...
252
253
  	data_area_of_buf2 = (char *)&pSMB2->hdr.Protocol +
  				get_unaligned_le16(&pSMB2->t2_rsp.DataOffset);
e4eb295d3   Steve French   [PATCH] cifs: Han...
254
255
256
257
  
  	data_area_of_target += total_in_buf;
  
  	/* copy second buffer into end of first buffer */
e4eb295d3   Steve French   [PATCH] cifs: Han...
258
  	total_in_buf += total_in_buf2;
2a2047bc9   Jeff Layton   cifs: sanitize le...
259
260
261
  	/* is the result too big for the field? */
  	if (total_in_buf > USHRT_MAX)
  		return -EPROTO;
26ec25486   Jeff Layton   cifs: fix unalign...
262
  	put_unaligned_le16(total_in_buf, &pSMBt->t2_rsp.DataCount);
2a2047bc9   Jeff Layton   cifs: sanitize le...
263
264
  
  	/* fix up the BCC */
820a803ff   Jeff Layton   cifs: keep BCC in...
265
  	byte_count = get_bcc(pTargetSMB);
e4eb295d3   Steve French   [PATCH] cifs: Han...
266
  	byte_count += total_in_buf2;
2a2047bc9   Jeff Layton   cifs: sanitize le...
267
268
269
  	/* is the result too big for the field? */
  	if (byte_count > USHRT_MAX)
  		return -EPROTO;
820a803ff   Jeff Layton   cifs: keep BCC in...
270
  	put_bcc(byte_count, pTargetSMB);
e4eb295d3   Steve French   [PATCH] cifs: Han...
271

be8e3b004   Steve French   consistently use ...
272
  	byte_count = be32_to_cpu(pTargetSMB->smb_buf_length);
e4eb295d3   Steve French   [PATCH] cifs: Han...
273
  	byte_count += total_in_buf2;
2a2047bc9   Jeff Layton   cifs: sanitize le...
274
275
276
  	/* don't allow buffer to overflow */
  	if (byte_count > CIFSMaxBufSize)
  		return -ENOBUFS;
be8e3b004   Steve French   consistently use ...
277
  	pTargetSMB->smb_buf_length = cpu_to_be32(byte_count);
e4eb295d3   Steve French   [PATCH] cifs: Han...
278

2a2047bc9   Jeff Layton   cifs: sanitize le...
279
  	memcpy(data_area_of_target, data_area_of_buf2, total_in_buf2);
fb8c4b14d   Steve French   [CIFS] whitespace...
280
  	if (remaining == total_in_buf2) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
281
  		cFYI(1, "found the last secondary response");
e4eb295d3   Steve French   [PATCH] cifs: Han...
282
283
284
  		return 0; /* we are done */
  	} else /* more responses to go */
  		return 1;
e4eb295d3   Steve French   [PATCH] cifs: Han...
285
  }
c74093b69   Jeff Layton   cifs: set up recu...
286
287
288
289
290
291
  static void
  cifs_echo_request(struct work_struct *work)
  {
  	int rc;
  	struct TCP_Server_Info *server = container_of(work,
  					struct TCP_Server_Info, echo.work);
247ec9b41   Jeff Layton   cifs: don't send ...
292
  	/*
195291e68   Jeff Layton   cifs: clean up ch...
293
294
295
  	 * We cannot send an echo until the NEGOTIATE_PROTOCOL request is
  	 * done, which is indicated by maxBuf != 0. Also, no need to ping if
  	 * we got a response recently
247ec9b41   Jeff Layton   cifs: don't send ...
296
  	 */
195291e68   Jeff Layton   cifs: clean up ch...
297
  	if (server->maxBuf == 0 ||
247ec9b41   Jeff Layton   cifs: don't send ...
298
  	    time_before(jiffies, server->lstrp + SMB_ECHO_INTERVAL - HZ))
c74093b69   Jeff Layton   cifs: set up recu...
299
300
301
302
303
304
305
306
307
308
  		goto requeue_echo;
  
  	rc = CIFSSMBEcho(server);
  	if (rc)
  		cFYI(1, "Unable to send echo request to server: %s",
  			server->hostname);
  
  requeue_echo:
  	queue_delayed_work(system_nrt_wq, &server->echo, SMB_ECHO_INTERVAL);
  }
3d9c2472a   Pavel Shilovsky   CIFS: Move buffer...
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
  static bool
  allocate_buffers(char **bigbuf, char **smallbuf, unsigned int size,
  		 bool is_large_buf)
  {
  	char *bbuf = *bigbuf, *sbuf = *smallbuf;
  
  	if (bbuf == NULL) {
  		bbuf = (char *)cifs_buf_get();
  		if (!bbuf) {
  			cERROR(1, "No memory for large SMB response");
  			msleep(3000);
  			/* retry will check if exiting */
  			return false;
  		}
  	} else if (is_large_buf) {
  		/* we are reusing a dirty large buf, clear its start */
  		memset(bbuf, 0, size);
  	}
  
  	if (sbuf == NULL) {
  		sbuf = (char *)cifs_small_buf_get();
  		if (!sbuf) {
  			cERROR(1, "No memory for SMB response");
  			msleep(1000);
  			/* retry will check if exiting */
  			return false;
  		}
  		/* beginning of smb buffer is cleared in our buf_get */
  	} else {
  		/* if existing small buf clear beginning */
  		memset(sbuf, 0, size);
  	}
  
  	*bigbuf = bbuf;
  	*smallbuf = sbuf;
  
  	return true;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
347
  static int
e7015fb1c   Pavel Shilovsky   CIFS: Simplify so...
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
  read_from_socket(struct TCP_Server_Info *server, struct msghdr *smb_msg,
  		 struct kvec *iov, unsigned int to_read,
  		 unsigned int *ptotal_read, bool is_header_read)
  {
  	int length, rc = 0;
  	unsigned int total_read;
  	char *buf = iov->iov_base;
  
  	for (total_read = 0; total_read < to_read; total_read += length) {
  		length = kernel_recvmsg(server->ssocket, smb_msg, iov, 1,
  					to_read - total_read, 0);
  		if (server->tcpStatus == CifsExiting) {
  			/* then will exit */
  			rc = 2;
  			break;
  		} else if (server->tcpStatus == CifsNeedReconnect) {
  			cifs_reconnect(server);
  			/* Reconnect wakes up rspns q */
  			/* Now we will reread sock */
  			rc = 1;
  			break;
  		} else if (length == -ERESTARTSYS ||
  			   length == -EAGAIN ||
  			   length == -EINTR) {
  			/*
  			 * Minimum sleep to prevent looping, allowing socket
  			 * to clear and app threads to set tcpStatus
  			 * CifsNeedReconnect if server hung.
  			 */
  			usleep_range(1000, 2000);
  			length = 0;
  			if (!is_header_read)
  				continue;
  			/* Special handling for header read */
  			if (total_read) {
  				iov->iov_base = (to_read - total_read) +
  						buf;
  				iov->iov_len = to_read - total_read;
  				smb_msg->msg_control = NULL;
  				smb_msg->msg_controllen = 0;
  				rc = 3;
  			} else
  				rc = 1;
  			break;
  		} else if (length <= 0) {
  			cERROR(1, "Received no data, expecting %d",
  			       to_read - total_read);
  			cifs_reconnect(server);
  			rc = 1;
  			break;
  		}
  	}
  
  	*ptotal_read = total_read;
  	return rc;
  }
98bac62c9   Pavel Shilovsky   CIFS: Move RFC100...
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
  static bool
  check_rfc1002_header(struct TCP_Server_Info *server, char *buf)
  {
  	char temp = *buf;
  	unsigned int pdu_length = be32_to_cpu(
  				((struct smb_hdr *)buf)->smb_buf_length);
  
  	/*
  	 * The first byte big endian of the length field,
  	 * is actually not part of the length but the type
  	 * with the most common, zero, as regular data.
  	 */
  	if (temp == (char) RFC1002_SESSION_KEEP_ALIVE) {
  		return false;
  	} else if (temp == (char)RFC1002_POSITIVE_SESSION_RESPONSE) {
  		cFYI(1, "Good RFC 1002 session rsp");
  		return false;
  	} else if (temp == (char)RFC1002_NEGATIVE_SESSION_RESPONSE) {
  		/*
  		 * We get this from Windows 98 instead of an error on
  		 * SMB negprot response.
  		 */
  		cFYI(1, "Negative RFC1002 Session Response Error 0x%x)",
  			pdu_length);
  		/* give server a second to clean up */
  		msleep(1000);
  		/*
  		 * Always try 445 first on reconnect since we get NACK
  		 * on some if we ever connected to port 139 (the NACK
  		 * is since we do not begin with RFC1001 session
  		 * initialize frame).
  		 */
  		cifs_set_port((struct sockaddr *)
  				&server->dstaddr, CIFS_PORT);
  		cifs_reconnect(server);
  		wake_up(&server->response_q);
  		return false;
  	} else if (temp != (char) 0) {
  		cERROR(1, "Unknown RFC 1002 frame");
  		cifs_dump_mem(" Received Data: ", buf, 4);
  		cifs_reconnect(server);
  		return false;
  	}
  
  	/* else we have an SMB response */
  	if ((pdu_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) ||
  	    (pdu_length < sizeof(struct smb_hdr) - 1 - 4)) {
  		cERROR(1, "Invalid size SMB length %d pdu_length %d",
  		       4, pdu_length+4);
  		cifs_reconnect(server);
  		wake_up(&server->response_q);
  		return false;
  	}
  
  	return true;
  }
ad69bae17   Pavel Shilovsky   CIFS: Move mid se...
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
  static struct mid_q_entry *
  find_cifs_mid(struct TCP_Server_Info *server, struct smb_hdr *buf,
  	      int *length, bool is_large_buf, bool *is_multi_rsp, char **bigbuf)
  {
  	struct mid_q_entry *mid = NULL, *tmp_mid, *ret = NULL;
  
  	spin_lock(&GlobalMid_Lock);
  	list_for_each_entry_safe(mid, tmp_mid, &server->pending_mid_q, qhead) {
  		if (mid->mid != buf->Mid ||
  		    mid->midState != MID_REQUEST_SUBMITTED ||
  		    mid->command != buf->Command)
  			continue;
  
  		if (*length == 0 && check2ndT2(buf, server->maxBuf) > 0) {
  			/* We have a multipart transact2 resp */
  			*is_multi_rsp = true;
  			if (mid->resp_buf) {
  				/* merge response - fix up 1st*/
  				*length = coalesce_t2(buf, mid->resp_buf);
  				if (*length > 0) {
  					*length = 0;
  					mid->multiRsp = true;
  					break;
  				}
  				/* All parts received or packet is malformed. */
  				mid->multiEnd = true;
  				goto multi_t2_fnd;
  			}
  			if (!is_large_buf) {
  				/*FIXME: switch to already allocated largebuf?*/
  				cERROR(1, "1st trans2 resp needs bigbuf");
  			} else {
  				/* Have first buffer */
  				mid->resp_buf = buf;
  				mid->largeBuf = true;
  				*bigbuf = NULL;
  			}
  			break;
  		}
  		mid->resp_buf = buf;
  		mid->largeBuf = is_large_buf;
  multi_t2_fnd:
  		if (*length == 0)
  			mid->midState = MID_RESPONSE_RECEIVED;
  		else
  			mid->midState = MID_RESPONSE_MALFORMED;
  #ifdef CONFIG_CIFS_STATS2
  		mid->when_received = jiffies;
  #endif
  		list_del_init(&mid->qhead);
  		ret = mid;
  		break;
  	}
  	spin_unlock(&GlobalMid_Lock);
  
  	return ret;
  }
762dfd105   Pavel Shilovsky   CIFS: Cleanup dem...
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
  static void clean_demultiplex_info(struct TCP_Server_Info *server)
  {
  	int length;
  
  	/* take it off the list, if it's not already */
  	spin_lock(&cifs_tcp_ses_lock);
  	list_del_init(&server->tcp_ses_list);
  	spin_unlock(&cifs_tcp_ses_lock);
  
  	spin_lock(&GlobalMid_Lock);
  	server->tcpStatus = CifsExiting;
  	spin_unlock(&GlobalMid_Lock);
  	wake_up_all(&server->response_q);
  
  	/*
  	 * Check if we have blocked requests that need to free. Note that
  	 * cifs_max_pending is normally 50, but can be set at module install
  	 * time to as little as two.
  	 */
  	spin_lock(&GlobalMid_Lock);
  	if (atomic_read(&server->inFlight) >= cifs_max_pending)
  		atomic_set(&server->inFlight, cifs_max_pending - 1);
  	/*
  	 * We do not want to set the max_pending too low or we could end up
  	 * with the counter going negative.
  	 */
  	spin_unlock(&GlobalMid_Lock);
  	/*
  	 * Although there should not be any requests blocked on this queue it
  	 * can not hurt to be paranoid and try to wake up requests that may
  	 * haven been blocked when more than 50 at time were on the wire to the
  	 * same server - they now will see the session is in exit state and get
  	 * out of SendReceive.
  	 */
  	wake_up_all(&server->request_q);
  	/* give those requests time to exit */
  	msleep(125);
  
  	if (server->ssocket) {
  		sock_release(server->ssocket);
  		server->ssocket = NULL;
  	}
  
  	if (!list_empty(&server->pending_mid_q)) {
  		struct list_head dispose_list;
  		struct mid_q_entry *mid_entry;
  		struct list_head *tmp, *tmp2;
  
  		INIT_LIST_HEAD(&dispose_list);
  		spin_lock(&GlobalMid_Lock);
  		list_for_each_safe(tmp, tmp2, &server->pending_mid_q) {
  			mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
  			cFYI(1, "Clearing mid 0x%x", mid_entry->mid);
  			mid_entry->midState = MID_SHUTDOWN;
  			list_move(&mid_entry->qhead, &dispose_list);
  		}
  		spin_unlock(&GlobalMid_Lock);
  
  		/* now walk dispose list and issue callbacks */
  		list_for_each_safe(tmp, tmp2, &dispose_list) {
  			mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
  			cFYI(1, "Callback mid 0x%x", mid_entry->mid);
  			list_del_init(&mid_entry->qhead);
  			mid_entry->callback(mid_entry);
  		}
  		/* 1/8th of sec is more than enough time for them to exit */
  		msleep(125);
  	}
  
  	if (!list_empty(&server->pending_mid_q)) {
  		/*
  		 * mpx threads have not exited yet give them at least the smb
  		 * send timeout time for long ops.
  		 *
  		 * Due to delays on oplock break requests, we need to wait at
  		 * least 45 seconds before giving up on a request getting a
  		 * response and going ahead and killing cifsd.
  		 */
  		cFYI(1, "Wait for exit from demultiplex thread");
  		msleep(46000);
  		/*
  		 * If threads still have not exited they are probably never
  		 * coming home not much else we can do but free the memory.
  		 */
  	}
  
  	kfree(server->hostname);
  	kfree(server);
  
  	length = atomic_dec_return(&tcpSesAllocCount);
  	if (length > 0)
  		mempool_resize(cifs_req_poolp, length + cifs_min_rcv,
  				GFP_KERNEL);
  }
e7015fb1c   Pavel Shilovsky   CIFS: Simplify so...
611
  static int
7c97c200e   Al Viro   cifs: fix the typ...
612
  cifs_demultiplex_thread(void *p)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
613
614
  {
  	int length;
7c97c200e   Al Viro   cifs: fix the typ...
615
  	struct TCP_Server_Info *server = p;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
616
  	unsigned int pdu_length, total_read;
3d9c2472a   Pavel Shilovsky   CIFS: Move buffer...
617
  	char *buf = NULL, *bigbuf = NULL, *smallbuf = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
618
619
620
  	struct smb_hdr *smb_buffer = NULL;
  	struct msghdr smb_msg;
  	struct kvec iov;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
621
622
  	struct task_struct *task_to_wake = NULL;
  	struct mid_q_entry *mid_entry;
4b18f2a9c   Steve French   [CIFS] convert us...
623
  	bool isLargeBuf = false;
ad69bae17   Pavel Shilovsky   CIFS: Move mid se...
624
  	bool isMultiRsp = false;
e7015fb1c   Pavel Shilovsky   CIFS: Simplify so...
625
  	int rc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
626

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
627
  	current->flags |= PF_MEMALLOC;
b6b38f704   Joe Perches   [CIFS] Neaten cER...
628
  	cFYI(1, "Demultiplex PID: %d", task_pid_nr(current));
93d0ec851   Jeff Layton   remove locking ar...
629
630
631
  
  	length = atomic_inc_return(&tcpSesAllocCount);
  	if (length > 1)
26f57364d   Steve French   [CIFS] formatting...
632
633
  		mempool_resize(cifs_req_poolp, length + cifs_min_rcv,
  				GFP_KERNEL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
634

831441862   Rafael J. Wysocki   Freezer: make ker...
635
  	set_freezable();
469ee614a   Jeff Layton   [CIFS] eliminate ...
636
  	while (server->tcpStatus != CifsExiting) {
ede1327ea   Steve French   [PATCH] cifs: Add...
637
638
  		if (try_to_freeze())
  			continue;
b8643e1b5   Steve French   [PATCH] cifs: Do ...
639

3d9c2472a   Pavel Shilovsky   CIFS: Move buffer...
640
641
642
  		if (!allocate_buffers(&bigbuf, &smallbuf,
  				      sizeof(struct smb_hdr), isLargeBuf))
  			continue;
b8643e1b5   Steve French   [PATCH] cifs: Do ...
643

4b18f2a9c   Steve French   [CIFS] convert us...
644
645
  		isLargeBuf = false;
  		isMultiRsp = false;
3d9c2472a   Pavel Shilovsky   CIFS: Move buffer...
646
647
648
  		smb_buffer = (struct smb_hdr *)smallbuf;
  		buf = smallbuf;
  		iov.iov_base = buf;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
649
650
651
  		iov.iov_len = 4;
  		smb_msg.msg_control = NULL;
  		smb_msg.msg_controllen = 0;
f01d5e14e   Steve French   [CIFS] fix for in...
652
  		pdu_length = 4; /* enough to get RFC1001 header */
fda359436   Steve French   [CIFS] cifs: reco...
653

f01d5e14e   Steve French   [CIFS] fix for in...
654
  incomplete_rcv:
fd88ce931   Steve French   [CIFS] cifs: clar...
655
  		if (echo_retries > 0 && server->tcpStatus == CifsGood &&
fda359436   Steve French   [CIFS] cifs: reco...
656
657
658
659
660
661
  		    time_after(jiffies, server->lstrp +
  					(echo_retries * SMB_ECHO_INTERVAL))) {
  			cERROR(1, "Server %s has not responded in %d seconds. "
  				  "Reconnecting...", server->hostname,
  				  (echo_retries * SMB_ECHO_INTERVAL / HZ));
  			cifs_reconnect(server);
fda359436   Steve French   [CIFS] cifs: reco...
662
663
664
  			wake_up(&server->response_q);
  			continue;
  		}
e7015fb1c   Pavel Shilovsky   CIFS: Simplify so...
665
666
667
668
669
  		rc = read_from_socket(server, &smb_msg, &iov, pdu_length,
  				      &total_read, true /* header read */);
  		if (rc == 3)
  			goto incomplete_rcv;
  		else if (rc == 2)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
670
  			break;
e7015fb1c   Pavel Shilovsky   CIFS: Simplify so...
671
  		else if (rc == 1)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
672
  			continue;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
673

98bac62c9   Pavel Shilovsky   CIFS: Move RFC100...
674
675
676
677
  		/*
  		 * The right amount was read from socket - 4 bytes,
  		 * so we can now interpret the length field.
  		 */
46810cbf3   Steve French   [PATCH] cifs: Eas...
678

98bac62c9   Pavel Shilovsky   CIFS: Move RFC100...
679
680
681
682
683
  		/*
  		 * Note that RFC 1001 length is big endian on the wire,
  		 * but we convert it here so it is always manipulated
  		 * as host byte order.
  		 */
be8e3b004   Steve French   consistently use ...
684
  		pdu_length = be32_to_cpu(smb_buffer->smb_buf_length);
70ca734a1   Steve French   [CIFS] Various mi...
685

b6b38f704   Joe Perches   [CIFS] Neaten cER...
686
  		cFYI(1, "rfc1002 length 0x%x", pdu_length+4);
98bac62c9   Pavel Shilovsky   CIFS: Move RFC100...
687
  		if (!check_rfc1002_header(server, buf))
fb8c4b14d   Steve French   [CIFS] whitespace...
688
  			continue;
e4eb295d3   Steve French   [PATCH] cifs: Han...
689
690
  
  		/* else length ok */
fb8c4b14d   Steve French   [CIFS] whitespace...
691
  		if (pdu_length > MAX_CIFS_SMALL_BUFFER_SIZE - 4) {
4b18f2a9c   Steve French   [CIFS] convert us...
692
  			isLargeBuf = true;
e4eb295d3   Steve French   [PATCH] cifs: Han...
693
  			memcpy(bigbuf, smallbuf, 4);
3d9c2472a   Pavel Shilovsky   CIFS: Move buffer...
694
695
  			smb_buffer = (struct smb_hdr *)bigbuf;
  			buf = bigbuf;
e4eb295d3   Steve French   [PATCH] cifs: Han...
696
  		}
e7015fb1c   Pavel Shilovsky   CIFS: Simplify so...
697

3d9c2472a   Pavel Shilovsky   CIFS: Move buffer...
698
  		iov.iov_base = 4 + buf;
e4eb295d3   Steve French   [PATCH] cifs: Han...
699
  		iov.iov_len = pdu_length;
e7015fb1c   Pavel Shilovsky   CIFS: Simplify so...
700
701
702
  		rc = read_from_socket(server, &smb_msg, &iov, pdu_length,
  				      &total_read, false);
  		if (rc == 2)
e4eb295d3   Steve French   [PATCH] cifs: Han...
703
  			break;
e7015fb1c   Pavel Shilovsky   CIFS: Simplify so...
704
  		else if (rc == 1)
e4eb295d3   Steve French   [PATCH] cifs: Han...
705
  			continue;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
706

9587fcff4   Jeff Layton   cifs: fix length ...
707
  		total_read += 4; /* account for rfc1002 hdr */
50c2f7538   Steve French   [CIFS] whitespace...
708

9587fcff4   Jeff Layton   cifs: fix length ...
709
  		dump_smb(smb_buffer, total_read);
71823baff   Jeff Layton   cifs: don't alway...
710
711
712
713
714
715
716
717
718
719
720
721
  
  		/*
  		 * We know that we received enough to get to the MID as we
  		 * checked the pdu_length earlier. Now check to see
  		 * if the rest of the header is OK. We borrow the length
  		 * var for the rest of the loop to avoid a new stack var.
  		 *
  		 * 48 bytes is enough to display the header and a little bit
  		 * into the payload for debugging purposes.
  		 */
  		length = checkSMB(smb_buffer, smb_buffer->Mid, total_read);
  		if (length != 0)
3d9c2472a   Pavel Shilovsky   CIFS: Move buffer...
722
723
  			cifs_dump_mem("Bad SMB: ", buf,
  				      min_t(unsigned int, total_read, 48));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
724

fda359436   Steve French   [CIFS] cifs: reco...
725
  		server->lstrp = jiffies;
ad69bae17   Pavel Shilovsky   CIFS: Move mid se...
726
727
  		mid_entry = find_cifs_mid(server, smb_buffer, &length,
  					  isLargeBuf, &isMultiRsp, &bigbuf);
2b84a36c5   Jeff Layton   cifs: allow for d...
728
  		if (mid_entry != NULL) {
3c1105df6   Jeff Layton   cifs: don't call ...
729
  			mid_entry->callback(mid_entry);
cd63499cb   Steve French   [PATCH] cifs: Han...
730
  			/* Was previous buf put in mpx struct for multi-rsp? */
fb8c4b14d   Steve French   [CIFS] whitespace...
731
  			if (!isMultiRsp) {
cd63499cb   Steve French   [PATCH] cifs: Han...
732
  				/* smb buffer will be freed by user thread */
26f57364d   Steve French   [CIFS] formatting...
733
  				if (isLargeBuf)
cd63499cb   Steve French   [PATCH] cifs: Han...
734
  					bigbuf = NULL;
26f57364d   Steve French   [CIFS] formatting...
735
  				else
cd63499cb   Steve French   [PATCH] cifs: Han...
736
737
  					smallbuf = NULL;
  			}
71823baff   Jeff Layton   cifs: don't alway...
738
739
740
  		} else if (length != 0) {
  			/* response sanity checks failed */
  			continue;
4b18f2a9c   Steve French   [CIFS] convert us...
741
742
  		} else if (!is_valid_oplock_break(smb_buffer, server) &&
  			   !isMultiRsp) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
743
  			cERROR(1, "No task to wake, unknown frame received! "
8097531a5   Jeff Layton   cifs: clean up ac...
744
  				   "NumMids %d", atomic_read(&midCount));
3d9c2472a   Pavel Shilovsky   CIFS: Move buffer...
745
  			cifs_dump_mem("Received Data is: ", buf,
70ca734a1   Steve French   [CIFS] Various mi...
746
  				      sizeof(struct smb_hdr));
3979877e5   Steve French   [CIFS] Support fo...
747
748
749
750
  #ifdef CONFIG_CIFS_DEBUG2
  			cifs_dump_detail(smb_buffer);
  			cifs_dump_mids(server);
  #endif /* CIFS_DEBUG2 */
50c2f7538   Steve French   [CIFS] whitespace...
751

e4eb295d3   Steve French   [PATCH] cifs: Han...
752
753
  		}
  	} /* end while !EXITING */
fd62cb7e7   Justin P. Mattock   fs:cifs:connect.c...
754
  	/* buffer usually freed in free_mid - need to free it here on exit */
a8a11d399   Mariusz Kozlowski   [CIFS] remove som...
755
756
  	cifs_buf_release(bigbuf);
  	if (smallbuf) /* no sense logging a debug message if NULL */
b8643e1b5   Steve French   [PATCH] cifs: Do ...
757
  		cifs_small_buf_release(smallbuf);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
758

b1c8d2b42   Jeff Layton   cifs: handle the ...
759
  	task_to_wake = xchg(&server->tsk, NULL);
762dfd105   Pavel Shilovsky   CIFS: Cleanup dem...
760
  	clean_demultiplex_info(server);
50c2f7538   Steve French   [CIFS] whitespace...
761

b1c8d2b42   Jeff Layton   cifs: handle the ...
762
763
764
765
766
767
768
769
770
  	/* if server->tsk was NULL then wait for a signal before exiting */
  	if (!task_to_wake) {
  		set_current_state(TASK_INTERRUPTIBLE);
  		while (!signal_pending(current)) {
  			schedule();
  			set_current_state(TASK_INTERRUPTIBLE);
  		}
  		set_current_state(TASK_RUNNING);
  	}
0468a2cf9   Jeff Layton   cifs: take module...
771
  	module_put_and_exit(0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
772
  }
c359cf3c6   Jeff Layton   [CIFS] add hostna...
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
  /* extract the host portion of the UNC string */
  static char *
  extract_hostname(const char *unc)
  {
  	const char *src;
  	char *dst, *delim;
  	unsigned int len;
  
  	/* skip double chars at beginning of string */
  	/* BB: check validity of these bytes? */
  	src = unc + 2;
  
  	/* delimiter between hostname and sharename is always '\\' now */
  	delim = strchr(src, '\\');
  	if (!delim)
  		return ERR_PTR(-EINVAL);
  
  	len = delim - src;
  	dst = kmalloc((len + 1), GFP_KERNEL);
  	if (dst == NULL)
  		return ERR_PTR(-ENOMEM);
  
  	memcpy(dst, src, len);
  	dst[len] = '\0';
  
  	return dst;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
800
  static int
b946845a9   Sean Finney   cifs: cifs_parse_...
801
  cifs_parse_mount_options(const char *mountdata, const char *devname,
50c2f7538   Steve French   [CIFS] whitespace...
802
  			 struct smb_vol *vol)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
803
  {
4906e50b3   Pavel Shilovsky   CIFS: Fix memory ...
804
  	char *value, *data, *end;
957df4535   Vasily Averin   possible memory c...
805
  	char *mountdata_copy = NULL, *options;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
806
807
  	unsigned int  temp_len, i, j;
  	char separator[2];
9b9d6b243   Jeff Layton   cifs: reinstate o...
808
809
810
811
  	short int override_uid = -1;
  	short int override_gid = -1;
  	bool uid_specified = false;
  	bool gid_specified = false;
884639996   Jeff Layton   cifs: remove Loca...
812
  	char *nodename = utsname()->nodename;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
813
814
  
  	separator[0] = ',';
50c2f7538   Steve French   [CIFS] whitespace...
815
  	separator[1] = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
816

884639996   Jeff Layton   cifs: remove Loca...
817
818
819
820
821
  	/*
  	 * does not have to be perfect mapping since field is
  	 * informational, only used for servers that do not support
  	 * port 445 and it can be overridden at mount time
  	 */
1397f2ee4   Jeff Layton   cifs: replace som...
822
823
  	memset(vol->source_rfc1001_name, 0x20, RFC1001_NAME_LEN);
  	for (i = 0; i < strnlen(nodename, RFC1001_NAME_LEN); i++)
884639996   Jeff Layton   cifs: remove Loca...
824
  		vol->source_rfc1001_name[i] = toupper(nodename[i]);
1397f2ee4   Jeff Layton   cifs: replace som...
825
  	vol->source_rfc1001_name[RFC1001_NAME_LEN] = 0;
a10faeb2a   Steve French   [CIFS] Support fo...
826
827
828
  	/* null target name indicates to use *SMBSERVR default called name
  	   if we end up sending RFC1001 session initialize */
  	vol->target_rfc1001_name[0] = 0;
3e4b3e1f6   Jeff Layton   cifs: add separat...
829
830
  	vol->cred_uid = current_uid();
  	vol->linux_uid = current_uid();
a001e5b55   David Howells   CRED: Wrap task c...
831
  	vol->linux_gid = current_gid();
f55ed1a83   Jeff Layton   cifs: tighten up ...
832
833
834
  
  	/* default to only allowing write access to owner of the mount */
  	vol->dir_mode = vol->file_mode = S_IRUGO | S_IXUGO | S_IWUSR;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
835
836
  
  	/* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
ac67055ef   Jeremy Allison   [CIFS] POSIX exte...
837
838
  	/* default is always to request posix paths. */
  	vol->posix_paths = 1;
a0c9217f6   Jeff Layton   cifs: make server...
839
840
  	/* default to using server inode numbers where available */
  	vol->server_ino = 1;
ac67055ef   Jeremy Allison   [CIFS] POSIX exte...
841

6d20e8406   Suresh Jayaraman   cifs: add attribu...
842
  	vol->actimeo = CIFS_DEF_ACTIMEO;
b946845a9   Sean Finney   cifs: cifs_parse_...
843
844
845
846
847
848
  	if (!mountdata)
  		goto cifs_parse_mount_err;
  
  	mountdata_copy = kstrndup(mountdata, PAGE_SIZE, GFP_KERNEL);
  	if (!mountdata_copy)
  		goto cifs_parse_mount_err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
849

b946845a9   Sean Finney   cifs: cifs_parse_...
850
  	options = mountdata_copy;
4906e50b3   Pavel Shilovsky   CIFS: Fix memory ...
851
  	end = options + strlen(options);
50c2f7538   Steve French   [CIFS] whitespace...
852
  	if (strncmp(options, "sep=", 4) == 0) {
fb8c4b14d   Steve French   [CIFS] whitespace...
853
  		if (options[4] != 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
854
855
856
  			separator[0] = options[4];
  			options += 5;
  		} else {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
857
  			cFYI(1, "Null separator not allowed");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
858
859
  		}
  	}
50c2f7538   Steve French   [CIFS] whitespace...
860

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
861
862
863
864
865
  	while ((data = strsep(&options, separator)) != NULL) {
  		if (!*data)
  			continue;
  		if ((value = strchr(data, '=')) != NULL)
  			*value++ = '\0';
50c2f7538   Steve French   [CIFS] whitespace...
866
867
  		/* Have to parse this before we parse for "user" */
  		if (strnicmp(data, "user_xattr", 10) == 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
868
  			vol->no_xattr = 0;
50c2f7538   Steve French   [CIFS] whitespace...
869
  		} else if (strnicmp(data, "nouser_xattr", 12) == 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
870
871
  			vol->no_xattr = 1;
  		} else if (strnicmp(data, "user", 4) == 0) {
4b952a9b0   Steve French   [CIFS] Allow null...
872
  			if (!value) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
873
874
875
  				printk(KERN_WARNING
  				       "CIFS: invalid or missing username
  ");
b946845a9   Sean Finney   cifs: cifs_parse_...
876
  				goto cifs_parse_mount_err;
fb8c4b14d   Steve French   [CIFS] whitespace...
877
  			} else if (!*value) {
4b952a9b0   Steve French   [CIFS] Allow null...
878
879
  				/* null user, ie anonymous, authentication */
  				vol->nullauth = 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
880
  			}
8727c8a85   Steve French   Allow user names ...
881
882
  			if (strnlen(value, MAX_USERNAME_SIZE) <
  						MAX_USERNAME_SIZE) {
b946845a9   Sean Finney   cifs: cifs_parse_...
883
884
885
886
887
888
889
  				vol->username = kstrdup(value, GFP_KERNEL);
  				if (!vol->username) {
  					printk(KERN_WARNING "CIFS: no memory "
  							    "for username
  ");
  					goto cifs_parse_mount_err;
  				}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
890
891
892
  			} else {
  				printk(KERN_WARNING "CIFS: username too long
  ");
b946845a9   Sean Finney   cifs: cifs_parse_...
893
  				goto cifs_parse_mount_err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
894
895
896
897
898
  			}
  		} else if (strnicmp(data, "pass", 4) == 0) {
  			if (!value) {
  				vol->password = NULL;
  				continue;
fb8c4b14d   Steve French   [CIFS] whitespace...
899
  			} else if (value[0] == 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
900
901
902
903
  				/* check if string begins with double comma
  				   since that would mean the password really
  				   does start with a comma, and would not
  				   indicate an empty string */
fb8c4b14d   Steve French   [CIFS] whitespace...
904
  				if (value[1] != separator[0]) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
905
906
907
908
909
910
911
  					vol->password = NULL;
  					continue;
  				}
  			}
  			temp_len = strlen(value);
  			/* removed password length check, NTLM passwords
  				can be arbitrarily long */
50c2f7538   Steve French   [CIFS] whitespace...
912
  			/* if comma in password, the string will be
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
913
914
915
916
917
918
919
920
  			prematurely null terminated.  Commas in password are
  			specified across the cifs mount interface by a double
  			comma ie ,, and a comma used as in other cases ie ','
  			as a parameter delimiter/separator is single and due
  			to the strsep above is temporarily zeroed. */
  
  			/* NB: password legally can have multiple commas and
  			the only illegal character in a password is null */
50c2f7538   Steve French   [CIFS] whitespace...
921
  			if ((value[temp_len] == 0) &&
4906e50b3   Pavel Shilovsky   CIFS: Fix memory ...
922
  			    (value + temp_len < end) &&
09d1db5c6   Steve French   [PATCH] cifs: imp...
923
  			    (value[temp_len+1] == separator[0])) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
924
925
  				/* reinsert comma */
  				value[temp_len] = separator[0];
50c2f7538   Steve French   [CIFS] whitespace...
926
927
  				temp_len += 2;  /* move after second comma */
  				while (value[temp_len] != 0)  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
928
  					if (value[temp_len] == separator[0]) {
50c2f7538   Steve French   [CIFS] whitespace...
929
  						if (value[temp_len+1] ==
09d1db5c6   Steve French   [PATCH] cifs: imp...
930
931
932
  						     separator[0]) {
  						/* skip second comma */
  							temp_len++;
50c2f7538   Steve French   [CIFS] whitespace...
933
  						} else {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
934
935
936
937
938
939
940
  						/* single comma indicating start
  							 of next parm */
  							break;
  						}
  					}
  					temp_len++;
  				}
fb8c4b14d   Steve French   [CIFS] whitespace...
941
  				if (value[temp_len] == 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
942
943
944
945
946
947
  					options = NULL;
  				} else {
  					value[temp_len] = 0;
  					/* point option to start of next parm */
  					options = value + temp_len + 1;
  				}
50c2f7538   Steve French   [CIFS] whitespace...
948
  				/* go from value to value + temp_len condensing
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
949
950
  				double commas to singles. Note that this ends up
  				allocating a few bytes too many, which is ok */
e915fc497   Pekka Enberg   [PATCH] fs: conve...
951
  				vol->password = kzalloc(temp_len, GFP_KERNEL);
fb8c4b14d   Steve French   [CIFS] whitespace...
952
  				if (vol->password == NULL) {
50c2f7538   Steve French   [CIFS] whitespace...
953
954
955
  					printk(KERN_WARNING "CIFS: no memory "
  							    "for password
  ");
b946845a9   Sean Finney   cifs: cifs_parse_...
956
  					goto cifs_parse_mount_err;
433dc24f2   Steve French   [PATCH] cifs: rem...
957
  				}
50c2f7538   Steve French   [CIFS] whitespace...
958
  				for (i = 0, j = 0; i < temp_len; i++, j++) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
959
  					vol->password[j] = value[i];
fb8c4b14d   Steve French   [CIFS] whitespace...
960
  					if (value[i] == separator[0]
09d1db5c6   Steve French   [PATCH] cifs: imp...
961
  						&& value[i+1] == separator[0]) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
962
963
964
965
966
967
  						/* skip second comma */
  						i++;
  					}
  				}
  				vol->password[j] = 0;
  			} else {
e915fc497   Pekka Enberg   [PATCH] fs: conve...
968
  				vol->password = kzalloc(temp_len+1, GFP_KERNEL);
fb8c4b14d   Steve French   [CIFS] whitespace...
969
  				if (vol->password == NULL) {
50c2f7538   Steve French   [CIFS] whitespace...
970
971
972
  					printk(KERN_WARNING "CIFS: no memory "
  							    "for password
  ");
b946845a9   Sean Finney   cifs: cifs_parse_...
973
  					goto cifs_parse_mount_err;
433dc24f2   Steve French   [PATCH] cifs: rem...
974
  				}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
975
976
  				strcpy(vol->password, value);
  			}
58f7f68f2   Jeff Layton   cifs: add addr= m...
977
978
  		} else if (!strnicmp(data, "ip", 2) ||
  			   !strnicmp(data, "addr", 4)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
979
980
  			if (!value || !*value) {
  				vol->UNCip = NULL;
50b64e3b7   Jeff Layton   cifs: fix IPv6 ad...
981
982
  			} else if (strnlen(value, INET6_ADDRSTRLEN) <
  							INET6_ADDRSTRLEN) {
b946845a9   Sean Finney   cifs: cifs_parse_...
983
984
985
986
987
988
989
  				vol->UNCip = kstrdup(value, GFP_KERNEL);
  				if (!vol->UNCip) {
  					printk(KERN_WARNING "CIFS: no memory "
  							    "for UNC IP
  ");
  					goto cifs_parse_mount_err;
  				}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
990
  			} else {
50c2f7538   Steve French   [CIFS] whitespace...
991
992
993
  				printk(KERN_WARNING "CIFS: ip address "
  						    "too long
  ");
b946845a9   Sean Finney   cifs: cifs_parse_...
994
  				goto cifs_parse_mount_err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
995
  			}
50c2f7538   Steve French   [CIFS] whitespace...
996
997
  		} else if (strnicmp(data, "sec", 3) == 0) {
  			if (!value || !*value) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
998
  				cERROR(1, "no security value specified");
50c2f7538   Steve French   [CIFS] whitespace...
999
1000
1001
  				continue;
  			} else if (strnicmp(value, "krb5i", 5) == 0) {
  				vol->secFlg |= CIFSSEC_MAY_KRB5 |
189acaaef   Steve French   [CIFS] Enable sec...
1002
  					CIFSSEC_MUST_SIGN;
bf8206791   Steve French   [CIFS] Kerberos a...
1003
  			} else if (strnicmp(value, "krb5p", 5) == 0) {
50c2f7538   Steve French   [CIFS] whitespace...
1004
1005
  				/* vol->secFlg |= CIFSSEC_MUST_SEAL |
  					CIFSSEC_MAY_KRB5; */
b6b38f704   Joe Perches   [CIFS] Neaten cER...
1006
  				cERROR(1, "Krb5 cifs privacy not supported");
b946845a9   Sean Finney   cifs: cifs_parse_...
1007
  				goto cifs_parse_mount_err;
bf8206791   Steve French   [CIFS] Kerberos a...
1008
  			} else if (strnicmp(value, "krb5", 4) == 0) {
750d1151a   Steve French   [CIFS] Fix alloca...
1009
  				vol->secFlg |= CIFSSEC_MAY_KRB5;
ac6839246   Steve French   [CIFS] Allow raw ...
1010
1011
1012
1013
1014
  			} else if (strnicmp(value, "ntlmsspi", 8) == 0) {
  				vol->secFlg |= CIFSSEC_MAY_NTLMSSP |
  					CIFSSEC_MUST_SIGN;
  			} else if (strnicmp(value, "ntlmssp", 7) == 0) {
  				vol->secFlg |= CIFSSEC_MAY_NTLMSSP;
bf8206791   Steve French   [CIFS] Kerberos a...
1015
  			} else if (strnicmp(value, "ntlmv2i", 7) == 0) {
750d1151a   Steve French   [CIFS] Fix alloca...
1016
  				vol->secFlg |= CIFSSEC_MAY_NTLMV2 |
189acaaef   Steve French   [CIFS] Enable sec...
1017
  					CIFSSEC_MUST_SIGN;
bf8206791   Steve French   [CIFS] Kerberos a...
1018
  			} else if (strnicmp(value, "ntlmv2", 6) == 0) {
750d1151a   Steve French   [CIFS] Fix alloca...
1019
  				vol->secFlg |= CIFSSEC_MAY_NTLMV2;
bf8206791   Steve French   [CIFS] Kerberos a...
1020
  			} else if (strnicmp(value, "ntlmi", 5) == 0) {
750d1151a   Steve French   [CIFS] Fix alloca...
1021
  				vol->secFlg |= CIFSSEC_MAY_NTLM |
189acaaef   Steve French   [CIFS] Enable sec...
1022
  					CIFSSEC_MUST_SIGN;
bf8206791   Steve French   [CIFS] Kerberos a...
1023
1024
  			} else if (strnicmp(value, "ntlm", 4) == 0) {
  				/* ntlm is default so can be turned off too */
750d1151a   Steve French   [CIFS] Fix alloca...
1025
  				vol->secFlg |= CIFSSEC_MAY_NTLM;
bf8206791   Steve French   [CIFS] Kerberos a...
1026
  			} else if (strnicmp(value, "nontlm", 6) == 0) {
189acaaef   Steve French   [CIFS] Enable sec...
1027
  				/* BB is there a better way to do this? */
750d1151a   Steve French   [CIFS] Fix alloca...
1028
  				vol->secFlg |= CIFSSEC_MAY_NTLMV2;
189acaaef   Steve French   [CIFS] Enable sec...
1029
1030
  #ifdef CONFIG_CIFS_WEAK_PW_HASH
  			} else if (strnicmp(value, "lanman", 6) == 0) {
50c2f7538   Steve French   [CIFS] whitespace...
1031
  				vol->secFlg |= CIFSSEC_MAY_LANMAN;
189acaaef   Steve French   [CIFS] Enable sec...
1032
  #endif
bf8206791   Steve French   [CIFS] Kerberos a...
1033
  			} else if (strnicmp(value, "none", 4) == 0) {
189acaaef   Steve French   [CIFS] Enable sec...
1034
  				vol->nullauth = 1;
50c2f7538   Steve French   [CIFS] whitespace...
1035
  			} else {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
1036
  				cERROR(1, "bad security option: %s", value);
b946845a9   Sean Finney   cifs: cifs_parse_...
1037
  				goto cifs_parse_mount_err;
50c2f7538   Steve French   [CIFS] whitespace...
1038
  			}
1cb06d0b5   Steve French   Introduce smb2 mo...
1039
1040
1041
1042
1043
1044
1045
1046
  		} else if (strnicmp(data, "vers", 3) == 0) {
  			if (!value || !*value) {
  				cERROR(1, "no protocol version specified"
  					  " after vers= mount option");
  			} else if ((strnicmp(value, "cifs", 4) == 0) ||
  				   (strnicmp(value, "1", 1) == 0)) {
  				/* this is the default */
  				continue;
1cb06d0b5   Steve French   Introduce smb2 mo...
1047
  			}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1048
1049
1050
1051
  		} else if ((strnicmp(data, "unc", 3) == 0)
  			   || (strnicmp(data, "target", 6) == 0)
  			   || (strnicmp(data, "path", 4) == 0)) {
  			if (!value || !*value) {
50c2f7538   Steve French   [CIFS] whitespace...
1052
1053
1054
  				printk(KERN_WARNING "CIFS: invalid path to "
  						    "network resource
  ");
b946845a9   Sean Finney   cifs: cifs_parse_...
1055
  				goto cifs_parse_mount_err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1056
1057
  			}
  			if ((temp_len = strnlen(value, 300)) < 300) {
50c2f7538   Steve French   [CIFS] whitespace...
1058
  				vol->UNC = kmalloc(temp_len+1, GFP_KERNEL);
4523cc304   Steve French   [CIFS] UID/GID ov...
1059
  				if (vol->UNC == NULL)
b946845a9   Sean Finney   cifs: cifs_parse_...
1060
  					goto cifs_parse_mount_err;
50c2f7538   Steve French   [CIFS] whitespace...
1061
  				strcpy(vol->UNC, value);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1062
1063
1064
  				if (strncmp(vol->UNC, "//", 2) == 0) {
  					vol->UNC[0] = '\\';
  					vol->UNC[1] = '\\';
50c2f7538   Steve French   [CIFS] whitespace...
1065
  				} else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1066
  					printk(KERN_WARNING
50c2f7538   Steve French   [CIFS] whitespace...
1067
1068
1069
  					       "CIFS: UNC Path does not begin "
  					       "with // or \\\\ 
  ");
b946845a9   Sean Finney   cifs: cifs_parse_...
1070
  					goto cifs_parse_mount_err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1071
1072
1073
1074
  				}
  			} else {
  				printk(KERN_WARNING "CIFS: UNC name too long
  ");
b946845a9   Sean Finney   cifs: cifs_parse_...
1075
  				goto cifs_parse_mount_err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1076
1077
1078
1079
1080
1081
  			}
  		} else if ((strnicmp(data, "domain", 3) == 0)
  			   || (strnicmp(data, "workgroup", 5) == 0)) {
  			if (!value || !*value) {
  				printk(KERN_WARNING "CIFS: invalid domain name
  ");
b946845a9   Sean Finney   cifs: cifs_parse_...
1082
  				goto cifs_parse_mount_err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1083
1084
1085
  			}
  			/* BB are there cases in which a comma can be valid in
  			a domain name and need special handling? */
3979877e5   Steve French   [CIFS] Support fo...
1086
  			if (strnlen(value, 256) < 256) {
b946845a9   Sean Finney   cifs: cifs_parse_...
1087
1088
1089
1090
1091
1092
1093
  				vol->domainname = kstrdup(value, GFP_KERNEL);
  				if (!vol->domainname) {
  					printk(KERN_WARNING "CIFS: no memory "
  							    "for domainname
  ");
  					goto cifs_parse_mount_err;
  				}
b6b38f704   Joe Perches   [CIFS] Neaten cER...
1094
  				cFYI(1, "Domain name set");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1095
  			} else {
50c2f7538   Steve French   [CIFS] whitespace...
1096
1097
1098
  				printk(KERN_WARNING "CIFS: domain name too "
  						    "long
  ");
b946845a9   Sean Finney   cifs: cifs_parse_...
1099
  				goto cifs_parse_mount_err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1100
  			}
3eb9a8893   Ben Greear   cifs: Allow bindi...
1101
1102
1103
1104
1105
1106
1107
  		} else if (strnicmp(data, "srcaddr", 7) == 0) {
  			vol->srcaddr.ss_family = AF_UNSPEC;
  
  			if (!value || !*value) {
  				printk(KERN_WARNING "CIFS: srcaddr value"
  				       " not specified.
  ");
b946845a9   Sean Finney   cifs: cifs_parse_...
1108
  				goto cifs_parse_mount_err;
3eb9a8893   Ben Greear   cifs: Allow bindi...
1109
1110
1111
  			}
  			i = cifs_convert_address((struct sockaddr *)&vol->srcaddr,
  						 value, strlen(value));
b235f371a   Dan Carpenter   cifs: cifs_conver...
1112
  			if (i == 0) {
3eb9a8893   Ben Greear   cifs: Allow bindi...
1113
1114
1115
1116
  				printk(KERN_WARNING "CIFS:  Could not parse"
  				       " srcaddr: %s
  ",
  				       value);
b946845a9   Sean Finney   cifs: cifs_parse_...
1117
  				goto cifs_parse_mount_err;
3eb9a8893   Ben Greear   cifs: Allow bindi...
1118
  			}
50c2f7538   Steve French   [CIFS] whitespace...
1119
1120
1121
1122
1123
  		} else if (strnicmp(data, "prefixpath", 10) == 0) {
  			if (!value || !*value) {
  				printk(KERN_WARNING
  					"CIFS: invalid path prefix
  ");
b946845a9   Sean Finney   cifs: cifs_parse_...
1124
  				goto cifs_parse_mount_err;
50c2f7538   Steve French   [CIFS] whitespace...
1125
1126
  			}
  			if ((temp_len = strnlen(value, 1024)) < 1024) {
4523cc304   Steve French   [CIFS] UID/GID ov...
1127
  				if (value[0] != '/')
2fe87f02a   Steve French   [CIFS] Support de...
1128
  					temp_len++;  /* missing leading slash */
50c2f7538   Steve French   [CIFS] whitespace...
1129
1130
  				vol->prepath = kmalloc(temp_len+1, GFP_KERNEL);
  				if (vol->prepath == NULL)
b946845a9   Sean Finney   cifs: cifs_parse_...
1131
  					goto cifs_parse_mount_err;
4523cc304   Steve French   [CIFS] UID/GID ov...
1132
  				if (value[0] != '/') {
2fe87f02a   Steve French   [CIFS] Support de...
1133
  					vol->prepath[0] = '/';
50c2f7538   Steve French   [CIFS] whitespace...
1134
  					strcpy(vol->prepath+1, value);
2fe87f02a   Steve French   [CIFS] Support de...
1135
  				} else
50c2f7538   Steve French   [CIFS] whitespace...
1136
  					strcpy(vol->prepath, value);
b6b38f704   Joe Perches   [CIFS] Neaten cER...
1137
  				cFYI(1, "prefix path %s", vol->prepath);
50c2f7538   Steve French   [CIFS] whitespace...
1138
1139
1140
  			} else {
  				printk(KERN_WARNING "CIFS: prefix too long
  ");
b946845a9   Sean Finney   cifs: cifs_parse_...
1141
  				goto cifs_parse_mount_err;
50c2f7538   Steve French   [CIFS] whitespace...
1142
  			}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1143
1144
  		} else if (strnicmp(data, "iocharset", 9) == 0) {
  			if (!value || !*value) {
63135e088   Steve French   [CIFS] More white...
1145
1146
1147
  				printk(KERN_WARNING "CIFS: invalid iocharset "
  						    "specified
  ");
b946845a9   Sean Finney   cifs: cifs_parse_...
1148
  				goto cifs_parse_mount_err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1149
1150
  			}
  			if (strnlen(value, 65) < 65) {
b946845a9   Sean Finney   cifs: cifs_parse_...
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
  				if (strnicmp(value, "default", 7)) {
  					vol->iocharset = kstrdup(value,
  								 GFP_KERNEL);
  
  					if (!vol->iocharset) {
  						printk(KERN_WARNING "CIFS: no "
  								   "memory for"
  								   "charset
  ");
  						goto cifs_parse_mount_err;
  					}
  				}
50c2f7538   Steve French   [CIFS] whitespace...
1163
1164
  				/* if iocharset not set then load_nls_default
  				   is used by caller */
b6b38f704   Joe Perches   [CIFS] Neaten cER...
1165
  				cFYI(1, "iocharset set to %s", value);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1166
  			} else {
63135e088   Steve French   [CIFS] More white...
1167
1168
1169
  				printk(KERN_WARNING "CIFS: iocharset name "
  						    "too long.
  ");
b946845a9   Sean Finney   cifs: cifs_parse_...
1170
  				goto cifs_parse_mount_err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1171
  			}
9b9d6b243   Jeff Layton   cifs: reinstate o...
1172
1173
1174
  		} else if (!strnicmp(data, "uid", 3) && value && *value) {
  			vol->linux_uid = simple_strtoul(value, &value, 0);
  			uid_specified = true;
bd7633195   Jeff Layton   cifs: add cruid= ...
1175
1176
  		} else if (!strnicmp(data, "cruid", 5) && value && *value) {
  			vol->cred_uid = simple_strtoul(value, &value, 0);
9b9d6b243   Jeff Layton   cifs: reinstate o...
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
  		} else if (!strnicmp(data, "forceuid", 8)) {
  			override_uid = 1;
  		} else if (!strnicmp(data, "noforceuid", 10)) {
  			override_uid = 0;
  		} else if (!strnicmp(data, "gid", 3) && value && *value) {
  			vol->linux_gid = simple_strtoul(value, &value, 0);
  			gid_specified = true;
  		} else if (!strnicmp(data, "forcegid", 8)) {
  			override_gid = 1;
  		} else if (!strnicmp(data, "noforcegid", 10)) {
  			override_gid = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
  		} else if (strnicmp(data, "file_mode", 4) == 0) {
  			if (value && *value) {
  				vol->file_mode =
  					simple_strtoul(value, &value, 0);
  			}
  		} else if (strnicmp(data, "dir_mode", 4) == 0) {
  			if (value && *value) {
  				vol->dir_mode =
  					simple_strtoul(value, &value, 0);
  			}
  		} else if (strnicmp(data, "dirmode", 4) == 0) {
  			if (value && *value) {
  				vol->dir_mode =
  					simple_strtoul(value, &value, 0);
  			}
  		} else if (strnicmp(data, "port", 4) == 0) {
  			if (value && *value) {
  				vol->port =
  					simple_strtoul(value, &value, 0);
  			}
  		} else if (strnicmp(data, "rsize", 5) == 0) {
  			if (value && *value) {
  				vol->rsize =
  					simple_strtoul(value, &value, 0);
  			}
  		} else if (strnicmp(data, "wsize", 5) == 0) {
  			if (value && *value) {
  				vol->wsize =
  					simple_strtoul(value, &value, 0);
  			}
  		} else if (strnicmp(data, "sockopt", 5) == 0) {
6a5fa2362   Steve French   [CIFS] Add suppor...
1219
  			if (!value || !*value) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
1220
  				cERROR(1, "no socket option specified");
6a5fa2362   Steve French   [CIFS] Add suppor...
1221
1222
1223
  				continue;
  			} else if (strnicmp(value, "TCP_NODELAY", 11) == 0) {
  				vol->sockopt_tcp_nodelay = 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1224
1225
1226
  			}
  		} else if (strnicmp(data, "netbiosname", 4) == 0) {
  			if (!value || !*value || (*value == ' ')) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
1227
  				cFYI(1, "invalid (empty) netbiosname");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1228
  			} else {
1397f2ee4   Jeff Layton   cifs: replace som...
1229
1230
1231
1232
1233
1234
1235
1236
1237
  				memset(vol->source_rfc1001_name, 0x20,
  					RFC1001_NAME_LEN);
  				/*
  				 * FIXME: are there cases in which a comma can
  				 * be valid in workstation netbios name (and
  				 * need special handling)?
  				 */
  				for (i = 0; i < RFC1001_NAME_LEN; i++) {
  					/* don't ucase netbiosname for user */
50c2f7538   Steve French   [CIFS] whitespace...
1238
  					if (value[i] == 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1239
  						break;
1397f2ee4   Jeff Layton   cifs: replace som...
1240
  					vol->source_rfc1001_name[i] = value[i];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1241
1242
1243
  				}
  				/* The string has 16th byte zero still from
  				set at top of the function  */
1397f2ee4   Jeff Layton   cifs: replace som...
1244
  				if (i == RFC1001_NAME_LEN && value[i] != 0)
50c2f7538   Steve French   [CIFS] whitespace...
1245
1246
1247
  					printk(KERN_WARNING "CIFS: netbiosname"
  						" longer than 15 truncated.
  ");
a10faeb2a   Steve French   [CIFS] Support fo...
1248
1249
1250
1251
  			}
  		} else if (strnicmp(data, "servern", 7) == 0) {
  			/* servernetbiosname specified override *SMBSERVER */
  			if (!value || !*value || (*value == ' ')) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
1252
  				cFYI(1, "empty server netbiosname specified");
a10faeb2a   Steve French   [CIFS] Support fo...
1253
1254
  			} else {
  				/* last byte, type, is 0x20 for servr type */
1397f2ee4   Jeff Layton   cifs: replace som...
1255
1256
  				memset(vol->target_rfc1001_name, 0x20,
  					RFC1001_NAME_LEN_WITH_NULL);
a10faeb2a   Steve French   [CIFS] Support fo...
1257

50c2f7538   Steve French   [CIFS] whitespace...
1258
  				for (i = 0; i < 15; i++) {
a10faeb2a   Steve French   [CIFS] Support fo...
1259
  				/* BB are there cases in which a comma can be
50c2f7538   Steve French   [CIFS] whitespace...
1260
1261
  				   valid in this workstation netbios name
  				   (and need special handling)? */
a10faeb2a   Steve French   [CIFS] Support fo...
1262

50c2f7538   Steve French   [CIFS] whitespace...
1263
1264
1265
  				/* user or mount helper must uppercase
  				   the netbiosname */
  					if (value[i] == 0)
a10faeb2a   Steve French   [CIFS] Support fo...
1266
1267
  						break;
  					else
50c2f7538   Steve French   [CIFS] whitespace...
1268
1269
  						vol->target_rfc1001_name[i] =
  								value[i];
a10faeb2a   Steve French   [CIFS] Support fo...
1270
1271
1272
  				}
  				/* The string has 16th byte zero still from
  				   set at top of the function  */
1397f2ee4   Jeff Layton   cifs: replace som...
1273
  				if (i == RFC1001_NAME_LEN && value[i] != 0)
50c2f7538   Steve French   [CIFS] whitespace...
1274
1275
1276
  					printk(KERN_WARNING "CIFS: server net"
  					"biosname longer than 15 truncated.
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1277
  			}
6d20e8406   Suresh Jayaraman   cifs: add attribu...
1278
1279
1280
1281
1282
1283
1284
  		} else if (strnicmp(data, "actimeo", 7) == 0) {
  			if (value && *value) {
  				vol->actimeo = HZ * simple_strtoul(value,
  								   &value, 0);
  				if (vol->actimeo > CIFS_MAX_ACTIMEO) {
  					cERROR(1, "CIFS: attribute cache"
  							"timeout too large");
b946845a9   Sean Finney   cifs: cifs_parse_...
1285
  					goto cifs_parse_mount_err;
6d20e8406   Suresh Jayaraman   cifs: add attribu...
1286
1287
  				}
  			}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1288
1289
1290
1291
  		} else if (strnicmp(data, "credentials", 4) == 0) {
  			/* ignore */
  		} else if (strnicmp(data, "version", 3) == 0) {
  			/* ignore */
50c2f7538   Steve French   [CIFS] whitespace...
1292
  		} else if (strnicmp(data, "guest", 5) == 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1293
  			/* ignore */
c9c7fa006   Steve French   Fix the conflict ...
1294
  		} else if (strnicmp(data, "rw", 2) == 0 && strlen(data) == 2) {
71a394faa   Steve French   [CIFS] remove unk...
1295
1296
1297
  			/* ignore */
  		} else if (strnicmp(data, "ro", 2) == 0) {
  			/* ignore */
edf1ae403   Steve French   [CIFS] Reduce num...
1298
1299
1300
1301
  		} else if (strnicmp(data, "noblocksend", 11) == 0) {
  			vol->noblocksnd = 1;
  		} else if (strnicmp(data, "noautotune", 10) == 0) {
  			vol->noautotune = 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1302
1303
1304
1305
1306
1307
1308
1309
  		} else if ((strnicmp(data, "suid", 4) == 0) ||
  				   (strnicmp(data, "nosuid", 6) == 0) ||
  				   (strnicmp(data, "exec", 4) == 0) ||
  				   (strnicmp(data, "noexec", 6) == 0) ||
  				   (strnicmp(data, "nodev", 5) == 0) ||
  				   (strnicmp(data, "noauto", 6) == 0) ||
  				   (strnicmp(data, "dev", 3) == 0)) {
  			/*  The mount tool or mount.cifs helper (if present)
50c2f7538   Steve French   [CIFS] whitespace...
1310
1311
1312
1313
1314
  			    uses these opts to set flags, and the flags are read
  			    by the kernel vfs layer before we get here (ie
  			    before read super) so there is no point trying to
  			    parse these options again and set anything and it
  			    is ok to just ignore them */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1315
  			continue;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1316
1317
1318
1319
1320
1321
1322
1323
  		} else if (strnicmp(data, "hard", 4) == 0) {
  			vol->retry = 1;
  		} else if (strnicmp(data, "soft", 4) == 0) {
  			vol->retry = 0;
  		} else if (strnicmp(data, "perm", 4) == 0) {
  			vol->noperm = 0;
  		} else if (strnicmp(data, "noperm", 6) == 0) {
  			vol->noperm = 1;
6a0b48245   Steve French   [PATCH] cifs: Add...
1324
1325
1326
1327
  		} else if (strnicmp(data, "mapchars", 8) == 0) {
  			vol->remap = 1;
  		} else if (strnicmp(data, "nomapchars", 10) == 0) {
  			vol->remap = 0;
50c2f7538   Steve French   [CIFS] whitespace...
1328
1329
1330
1331
  		} else if (strnicmp(data, "sfu", 3) == 0) {
  			vol->sfu_emul = 1;
  		} else if (strnicmp(data, "nosfu", 5) == 0) {
  			vol->sfu_emul = 0;
2c1b86153   Steve French   [CIFS] Add nodfs ...
1332
1333
  		} else if (strnicmp(data, "nodfs", 5) == 0) {
  			vol->nodfs = 1;
ac67055ef   Jeremy Allison   [CIFS] POSIX exte...
1334
1335
1336
1337
  		} else if (strnicmp(data, "posixpaths", 10) == 0) {
  			vol->posix_paths = 1;
  		} else if (strnicmp(data, "noposixpaths", 12) == 0) {
  			vol->posix_paths = 0;
c18c842b1   Steve French   [CIFS] Allow disa...
1338
1339
1340
1341
  		} else if (strnicmp(data, "nounix", 6) == 0) {
  			vol->no_linux_ext = 1;
  		} else if (strnicmp(data, "nolinux", 7) == 0) {
  			vol->no_linux_ext = 1;
50c2f7538   Steve French   [CIFS] whitespace...
1342
  		} else if ((strnicmp(data, "nocase", 6) == 0) ||
a10faeb2a   Steve French   [CIFS] Support fo...
1343
  			   (strnicmp(data, "ignorecase", 10)  == 0)) {
50c2f7538   Steve French   [CIFS] whitespace...
1344
  			vol->nocase = 1;
f636a3480   Jeff Layton   cifs: ignore the ...
1345
1346
1347
1348
1349
1350
  		} else if (strnicmp(data, "mand", 4) == 0) {
  			/* ignore */
  		} else if (strnicmp(data, "nomand", 6) == 0) {
  			/* ignore */
  		} else if (strnicmp(data, "_netdev", 7) == 0) {
  			/* ignore */
c46fa8acd   Steve French   [CIFS] Add mount ...
1351
1352
  		} else if (strnicmp(data, "brl", 3) == 0) {
  			vol->nobrl =  0;
50c2f7538   Steve French   [CIFS] whitespace...
1353
  		} else if ((strnicmp(data, "nobrl", 5) == 0) ||
1c9551878   Steve French   [CIFS] Add suppor...
1354
  			   (strnicmp(data, "nolock", 6) == 0)) {
c46fa8acd   Steve French   [CIFS] Add mount ...
1355
  			vol->nobrl =  1;
d3485d37c   Steve French   [CIFS] Finish cif...
1356
1357
1358
  			/* turn off mandatory locking in mode
  			if remote locking is turned off since the
  			local vfs will do advisory */
50c2f7538   Steve French   [CIFS] whitespace...
1359
1360
  			if (vol->file_mode ==
  				(S_IALLUGO & ~(S_ISUID | S_IXGRP)))
d3485d37c   Steve French   [CIFS] Finish cif...
1361
  				vol->file_mode = S_IALLUGO;
13a6e42af   Steve French   [CIFS] add mount ...
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
  		} else if (strnicmp(data, "forcemandatorylock", 9) == 0) {
  			/* will take the shorter form "forcemand" as well */
  			/* This mount option will force use of mandatory
  			  (DOS/Windows style) byte range locks, instead of
  			  using posix advisory byte range locks, even if the
  			  Unix extensions are available and posix locks would
  			  be supported otherwise. If Unix extensions are not
  			  negotiated this has no effect since mandatory locks
  			  would be used (mandatory locks is all that those
  			  those servers support) */
  			vol->mand_lock = 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1373
1374
1375
1376
  		} else if (strnicmp(data, "setuids", 7) == 0) {
  			vol->setuids = 1;
  		} else if (strnicmp(data, "nosetuids", 9) == 0) {
  			vol->setuids = 0;
d0a9c078d   Jeff Layton   [CIFS] CIFS curre...
1377
1378
1379
1380
  		} else if (strnicmp(data, "dynperm", 7) == 0) {
  			vol->dynperm = true;
  		} else if (strnicmp(data, "nodynperm", 9) == 0) {
  			vol->dynperm = false;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1381
1382
1383
1384
1385
1386
1387
1388
  		} else if (strnicmp(data, "nohard", 6) == 0) {
  			vol->retry = 0;
  		} else if (strnicmp(data, "nosoft", 6) == 0) {
  			vol->retry = 1;
  		} else if (strnicmp(data, "nointr", 6) == 0) {
  			vol->intr = 0;
  		} else if (strnicmp(data, "intr", 4) == 0) {
  			vol->intr = 1;
be652445f   Steve French   [CIFS] Add new no...
1389
1390
1391
1392
  		} else if (strnicmp(data, "nostrictsync", 12) == 0) {
  			vol->nostrictsync = 1;
  		} else if (strnicmp(data, "strictsync", 10) == 0) {
  			vol->nostrictsync = 0;
50c2f7538   Steve French   [CIFS] whitespace...
1393
  		} else if (strnicmp(data, "serverino", 7) == 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1394
  			vol->server_ino = 1;
50c2f7538   Steve French   [CIFS] whitespace...
1395
  		} else if (strnicmp(data, "noserverino", 9) == 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1396
  			vol->server_ino = 0;
c9c7fa006   Steve French   Fix the conflict ...
1397
  		} else if (strnicmp(data, "rwpidforward", 12) == 0) {
d4ffff1fa   Pavel Shilovsky   CIFS: Add rwpidfo...
1398
  			vol->rwpidforward = 1;
50c2f7538   Steve French   [CIFS] whitespace...
1399
  		} else if (strnicmp(data, "cifsacl", 7) == 0) {
0a4b92c05   Steve French   [CIFS] Add worker...
1400
1401
1402
  			vol->cifs_acl = 1;
  		} else if (strnicmp(data, "nocifsacl", 9) == 0) {
  			vol->cifs_acl = 0;
50c2f7538   Steve French   [CIFS] whitespace...
1403
  		} else if (strnicmp(data, "acl", 3) == 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1404
  			vol->no_psx_acl = 0;
50c2f7538   Steve French   [CIFS] whitespace...
1405
  		} else if (strnicmp(data, "noacl", 5) == 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1406
  			vol->no_psx_acl = 1;
84210e912   Steve French   [CIFS] improve se...
1407
1408
  		} else if (strnicmp(data, "locallease", 6) == 0) {
  			vol->local_lease = 1;
50c2f7538   Steve French   [CIFS] whitespace...
1409
  		} else if (strnicmp(data, "sign", 4) == 0) {
750d1151a   Steve French   [CIFS] Fix alloca...
1410
  			vol->secFlg |= CIFSSEC_MUST_SIGN;
95b1cb90b   Steve French   [CIFS] enable par...
1411
1412
1413
1414
1415
1416
  		} else if (strnicmp(data, "seal", 4) == 0) {
  			/* we do not do the following in secFlags because seal
  			   is a per tree connection (mount) not a per socket
  			   or per-smb connection option in the protocol */
  			/* vol->secFlg |= CIFSSEC_MUST_SEAL; */
  			vol->seal = 1;
50c2f7538   Steve French   [CIFS] whitespace...
1417
  		} else if (strnicmp(data, "direct", 6) == 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1418
  			vol->direct_io = 1;
50c2f7538   Steve French   [CIFS] whitespace...
1419
  		} else if (strnicmp(data, "forcedirectio", 13) == 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1420
  			vol->direct_io = 1;
d39454ffe   Pavel Shilovsky   CIFS: Add strictc...
1421
1422
  		} else if (strnicmp(data, "strictcache", 11) == 0) {
  			vol->strict_io = 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1423
  		} else if (strnicmp(data, "noac", 4) == 0) {
50c2f7538   Steve French   [CIFS] whitespace...
1424
1425
1426
1427
  			printk(KERN_WARNING "CIFS: Mount option noac not "
  				"supported. Instead set "
  				"/proc/fs/cifs/LookupCacheEnabled to 0
  ");
fa1df75d4   Suresh Jayaraman   cifs: add mount o...
1428
  		} else if (strnicmp(data, "fsc", 3) == 0) {
607a569da   Suresh Jayaraman   cifs: allow fsc m...
1429
  #ifndef CONFIG_CIFS_FSCACHE
83fb086e0   Jeff Layton   cifs: trivial: ad...
1430
  			cERROR(1, "FS-Cache support needs CONFIG_CIFS_FSCACHE "
607a569da   Suresh Jayaraman   cifs: allow fsc m...
1431
  				  "kernel config option set");
b946845a9   Sean Finney   cifs: cifs_parse_...
1432
  			goto cifs_parse_mount_err;
607a569da   Suresh Jayaraman   cifs: allow fsc m...
1433
  #endif
fa1df75d4   Suresh Jayaraman   cifs: add mount o...
1434
  			vol->fsc = true;
736a33205   Stefan Metzmacher   cifs: add "mfsyml...
1435
1436
  		} else if (strnicmp(data, "mfsymlinks", 10) == 0) {
  			vol->mfsymlinks = true;
0eb8a132c   Jeff Layton   cifs: add "multiu...
1437
1438
  		} else if (strnicmp(data, "multiuser", 8) == 0) {
  			vol->multiuser = true;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1439
  		} else
50c2f7538   Steve French   [CIFS] whitespace...
1440
1441
1442
  			printk(KERN_WARNING "CIFS: Unknown mount option %s
  ",
  						data);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1443
1444
  	}
  	if (vol->UNC == NULL) {
4523cc304   Steve French   [CIFS] UID/GID ov...
1445
  		if (devname == NULL) {
50c2f7538   Steve French   [CIFS] whitespace...
1446
1447
1448
  			printk(KERN_WARNING "CIFS: Missing UNC name for mount "
  						"target
  ");
b946845a9   Sean Finney   cifs: cifs_parse_...
1449
  			goto cifs_parse_mount_err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1450
1451
  		}
  		if ((temp_len = strnlen(devname, 300)) < 300) {
50c2f7538   Steve French   [CIFS] whitespace...
1452
  			vol->UNC = kmalloc(temp_len+1, GFP_KERNEL);
4523cc304   Steve French   [CIFS] UID/GID ov...
1453
  			if (vol->UNC == NULL)
b946845a9   Sean Finney   cifs: cifs_parse_...
1454
  				goto cifs_parse_mount_err;
50c2f7538   Steve French   [CIFS] whitespace...
1455
  			strcpy(vol->UNC, devname);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1456
1457
1458
1459
  			if (strncmp(vol->UNC, "//", 2) == 0) {
  				vol->UNC[0] = '\\';
  				vol->UNC[1] = '\\';
  			} else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
50c2f7538   Steve French   [CIFS] whitespace...
1460
1461
1462
  				printk(KERN_WARNING "CIFS: UNC Path does not "
  						    "begin with // or \\\\ 
  ");
b946845a9   Sean Finney   cifs: cifs_parse_...
1463
  				goto cifs_parse_mount_err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1464
  			}
7c5e628f9   Igor Mammedov   [CIFS] Fixed buil...
1465
1466
1467
  			value = strpbrk(vol->UNC+2, "/\\");
  			if (value)
  				*value = '\\';
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1468
1469
1470
  		} else {
  			printk(KERN_WARNING "CIFS: UNC name too long
  ");
b946845a9   Sean Finney   cifs: cifs_parse_...
1471
  			goto cifs_parse_mount_err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1472
1473
  		}
  	}
0eb8a132c   Jeff Layton   cifs: add "multiu...
1474
1475
1476
1477
  
  	if (vol->multiuser && !(vol->secFlg & CIFSSEC_MAY_KRB5)) {
  		cERROR(1, "Multiuser mounts currently require krb5 "
  			  "authentication!");
b946845a9   Sean Finney   cifs: cifs_parse_...
1478
  		goto cifs_parse_mount_err;
0eb8a132c   Jeff Layton   cifs: add "multiu...
1479
  	}
fb8c4b14d   Steve French   [CIFS] whitespace...
1480
  	if (vol->UNCip == NULL)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1481
  		vol->UNCip = &vol->UNC[2];
9b9d6b243   Jeff Layton   cifs: reinstate o...
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
  	if (uid_specified)
  		vol->override_uid = override_uid;
  	else if (override_uid == 1)
  		printk(KERN_NOTICE "CIFS: ignoring forceuid mount option "
  				   "specified with no uid= option.
  ");
  
  	if (gid_specified)
  		vol->override_gid = override_gid;
  	else if (override_gid == 1)
  		printk(KERN_NOTICE "CIFS: ignoring forcegid mount option "
  				   "specified with no gid= option.
  ");
b946845a9   Sean Finney   cifs: cifs_parse_...
1495
  	kfree(mountdata_copy);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1496
  	return 0;
b946845a9   Sean Finney   cifs: cifs_parse_...
1497
1498
1499
1500
  
  cifs_parse_mount_err:
  	kfree(mountdata_copy);
  	return 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1501
  }
3eb9a8893   Ben Greear   cifs: Allow bindi...
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
  /** Returns true if srcaddr isn't specified and rhs isn't
   * specified, or if srcaddr is specified and
   * matches the IP address of the rhs argument.
   */
  static bool
  srcip_matches(struct sockaddr *srcaddr, struct sockaddr *rhs)
  {
  	switch (srcaddr->sa_family) {
  	case AF_UNSPEC:
  		return (rhs->sa_family == AF_UNSPEC);
  	case AF_INET: {
  		struct sockaddr_in *saddr4 = (struct sockaddr_in *)srcaddr;
  		struct sockaddr_in *vaddr4 = (struct sockaddr_in *)rhs;
  		return (saddr4->sin_addr.s_addr == vaddr4->sin_addr.s_addr);
  	}
  	case AF_INET6: {
  		struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *)srcaddr;
  		struct sockaddr_in6 *vaddr6 = (struct sockaddr_in6 *)&rhs;
  		return ipv6_addr_equal(&saddr6->sin6_addr, &vaddr6->sin6_addr);
  	}
  	default:
  		WARN_ON(1);
  		return false; /* don't expect to be here */
  	}
  }
4b886136d   Pavel Shilovsky   CIFS: Add match_p...
1527
1528
1529
1530
1531
1532
1533
1534
  /*
   * If no port is specified in addr structure, we try to match with 445 port
   * and if it fails - with 139 ports. It should be called only if address
   * families of server and addr are equal.
   */
  static bool
  match_port(struct TCP_Server_Info *server, struct sockaddr *addr)
  {
6da979106   Steve French   Elminate sparse _...
1535
  	__be16 port, *sport;
4b886136d   Pavel Shilovsky   CIFS: Add match_p...
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
  
  	switch (addr->sa_family) {
  	case AF_INET:
  		sport = &((struct sockaddr_in *) &server->dstaddr)->sin_port;
  		port = ((struct sockaddr_in *) addr)->sin_port;
  		break;
  	case AF_INET6:
  		sport = &((struct sockaddr_in6 *) &server->dstaddr)->sin6_port;
  		port = ((struct sockaddr_in6 *) addr)->sin6_port;
  		break;
  	default:
  		WARN_ON(1);
  		return false;
  	}
  
  	if (!port) {
  		port = htons(CIFS_PORT);
  		if (port == *sport)
  			return true;
  
  		port = htons(RFC1001_PORT);
  	}
  
  	return port == *sport;
  }
3eb9a8893   Ben Greear   cifs: Allow bindi...
1561

4515148ef   Jeff Layton   cifs: move addres...
1562
  static bool
3eb9a8893   Ben Greear   cifs: Allow bindi...
1563
1564
  match_address(struct TCP_Server_Info *server, struct sockaddr *addr,
  	      struct sockaddr *srcaddr)
4515148ef   Jeff Layton   cifs: move addres...
1565
  {
4515148ef   Jeff Layton   cifs: move addres...
1566
  	switch (addr->sa_family) {
a9f1b85e5   Pavel Shilovsky   CIFS: Simplify ip...
1567
1568
1569
1570
1571
1572
  	case AF_INET: {
  		struct sockaddr_in *addr4 = (struct sockaddr_in *)addr;
  		struct sockaddr_in *srv_addr4 =
  					(struct sockaddr_in *)&server->dstaddr;
  
  		if (addr4->sin_addr.s_addr != srv_addr4->sin_addr.s_addr)
4515148ef   Jeff Layton   cifs: move addres...
1573
  			return false;
4515148ef   Jeff Layton   cifs: move addres...
1574
  		break;
a9f1b85e5   Pavel Shilovsky   CIFS: Simplify ip...
1575
1576
1577
1578
1579
  	}
  	case AF_INET6: {
  		struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr;
  		struct sockaddr_in6 *srv_addr6 =
  					(struct sockaddr_in6 *)&server->dstaddr;
4515148ef   Jeff Layton   cifs: move addres...
1580
  		if (!ipv6_addr_equal(&addr6->sin6_addr,
a9f1b85e5   Pavel Shilovsky   CIFS: Simplify ip...
1581
  				     &srv_addr6->sin6_addr))
4515148ef   Jeff Layton   cifs: move addres...
1582
  			return false;
a9f1b85e5   Pavel Shilovsky   CIFS: Simplify ip...
1583
  		if (addr6->sin6_scope_id != srv_addr6->sin6_scope_id)
4515148ef   Jeff Layton   cifs: move addres...
1584
  			return false;
4515148ef   Jeff Layton   cifs: move addres...
1585
1586
  		break;
  	}
a9f1b85e5   Pavel Shilovsky   CIFS: Simplify ip...
1587
1588
1589
1590
  	default:
  		WARN_ON(1);
  		return false; /* don't expect to be here */
  	}
4515148ef   Jeff Layton   cifs: move addres...
1591

3eb9a8893   Ben Greear   cifs: Allow bindi...
1592
1593
  	if (!srcip_matches(srcaddr, (struct sockaddr *)&server->srcaddr))
  		return false;
4515148ef   Jeff Layton   cifs: move addres...
1594
1595
  	return true;
  }
daf5b0b6f   Jeff Layton   cifs: match secTy...
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
  static bool
  match_security(struct TCP_Server_Info *server, struct smb_vol *vol)
  {
  	unsigned int secFlags;
  
  	if (vol->secFlg & (~(CIFSSEC_MUST_SIGN | CIFSSEC_MUST_SEAL)))
  		secFlags = vol->secFlg;
  	else
  		secFlags = global_secflags | vol->secFlg;
  
  	switch (server->secType) {
  	case LANMAN:
  		if (!(secFlags & (CIFSSEC_MAY_LANMAN|CIFSSEC_MAY_PLNTXT)))
  			return false;
  		break;
  	case NTLMv2:
  		if (!(secFlags & CIFSSEC_MAY_NTLMV2))
  			return false;
  		break;
  	case NTLM:
  		if (!(secFlags & CIFSSEC_MAY_NTLM))
  			return false;
  		break;
  	case Kerberos:
  		if (!(secFlags & CIFSSEC_MAY_KRB5))
  			return false;
  		break;
  	case RawNTLMSSP:
  		if (!(secFlags & CIFSSEC_MAY_NTLMSSP))
  			return false;
  		break;
  	default:
  		/* shouldn't happen */
  		return false;
  	}
25985edce   Lucas De Marchi   Fix common misspe...
1631
  	/* now check if signing mode is acceptable */
daf5b0b6f   Jeff Layton   cifs: match secTy...
1632
  	if ((secFlags & CIFSSEC_MAY_SIGN) == 0 &&
96daf2b09   Steve French   [CIFS] Rename thr...
1633
  	    (server->sec_mode & SECMODE_SIGN_REQUIRED))
daf5b0b6f   Jeff Layton   cifs: match secTy...
1634
1635
  			return false;
  	else if (((secFlags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN) &&
96daf2b09   Steve French   [CIFS] Rename thr...
1636
  		 (server->sec_mode &
daf5b0b6f   Jeff Layton   cifs: match secTy...
1637
1638
1639
1640
1641
  		  (SECMODE_SIGN_ENABLED|SECMODE_SIGN_REQUIRED)) == 0)
  			return false;
  
  	return true;
  }
37bb04e5a   Pavel Shilovsky   CIFS: Simplify co...
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
  static int match_server(struct TCP_Server_Info *server, struct sockaddr *addr,
  			 struct smb_vol *vol)
  {
  	if (!net_eq(cifs_net_ns(server), current->nsproxy->net_ns))
  		return 0;
  
  	if (!match_address(server, addr,
  			   (struct sockaddr *)&vol->srcaddr))
  		return 0;
  
  	if (!match_port(server, addr))
  		return 0;
  
  	if (!match_security(server, vol))
  		return 0;
  
  	return 1;
  }
e7ddee903   Jeff Layton   cifs: disable sha...
1660
  static struct TCP_Server_Info *
daf5b0b6f   Jeff Layton   cifs: match secTy...
1661
  cifs_find_tcp_session(struct sockaddr *addr, struct smb_vol *vol)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1662
  {
e7ddee903   Jeff Layton   cifs: disable sha...
1663
  	struct TCP_Server_Info *server;
e7ddee903   Jeff Layton   cifs: disable sha...
1664

3f9bcca78   Suresh Jayaraman   cifs: convert cif...
1665
  	spin_lock(&cifs_tcp_ses_lock);
4515148ef   Jeff Layton   cifs: move addres...
1666
  	list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) {
37bb04e5a   Pavel Shilovsky   CIFS: Simplify co...
1667
  		if (!match_server(server, addr, vol))
daf5b0b6f   Jeff Layton   cifs: match secTy...
1668
  			continue;
e7ddee903   Jeff Layton   cifs: disable sha...
1669
  		++server->srv_count;
3f9bcca78   Suresh Jayaraman   cifs: convert cif...
1670
  		spin_unlock(&cifs_tcp_ses_lock);
b6b38f704   Joe Perches   [CIFS] Neaten cER...
1671
  		cFYI(1, "Existing tcp session with server found");
e7ddee903   Jeff Layton   cifs: disable sha...
1672
  		return server;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1673
  	}
3f9bcca78   Suresh Jayaraman   cifs: convert cif...
1674
  	spin_unlock(&cifs_tcp_ses_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1675
1676
  	return NULL;
  }
1b20d6721   Cyrill Gorcunov   [CIFS] cifs_find_...
1677

14fbf50d6   Jeff Layton   cifs: reinstate s...
1678
  static void
e7ddee903   Jeff Layton   cifs: disable sha...
1679
  cifs_put_tcp_session(struct TCP_Server_Info *server)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1680
  {
e7ddee903   Jeff Layton   cifs: disable sha...
1681
  	struct task_struct *task;
1b20d6721   Cyrill Gorcunov   [CIFS] cifs_find_...
1682

3f9bcca78   Suresh Jayaraman   cifs: convert cif...
1683
  	spin_lock(&cifs_tcp_ses_lock);
e7ddee903   Jeff Layton   cifs: disable sha...
1684
  	if (--server->srv_count > 0) {
3f9bcca78   Suresh Jayaraman   cifs: convert cif...
1685
  		spin_unlock(&cifs_tcp_ses_lock);
e7ddee903   Jeff Layton   cifs: disable sha...
1686
  		return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1687
  	}
1b20d6721   Cyrill Gorcunov   [CIFS] cifs_find_...
1688

f1d0c9986   Rob Landley   Make CIFS mount w...
1689
  	put_net(cifs_net_ns(server));
e7ddee903   Jeff Layton   cifs: disable sha...
1690
  	list_del_init(&server->tcp_ses_list);
3f9bcca78   Suresh Jayaraman   cifs: convert cif...
1691
  	spin_unlock(&cifs_tcp_ses_lock);
dea570e08   Steve French   [CIFS] Remove ove...
1692

c74093b69   Jeff Layton   cifs: set up recu...
1693
  	cancel_delayed_work_sync(&server->echo);
e7ddee903   Jeff Layton   cifs: disable sha...
1694
1695
1696
  	spin_lock(&GlobalMid_Lock);
  	server->tcpStatus = CifsExiting;
  	spin_unlock(&GlobalMid_Lock);
dea570e08   Steve French   [CIFS] Remove ove...
1697

d2b915210   Shirish Pargaonkar   NTLM auth and sig...
1698
  	cifs_crypto_shash_release(server);
488f1d2d6   Suresh Jayaraman   cifs: define serv...
1699
  	cifs_fscache_release_client_cookie(server);
21e733930   Shirish Pargaonkar   NTLM auth and sig...
1700
1701
1702
  	kfree(server->session_key.response);
  	server->session_key.response = NULL;
  	server->session_key.len = 0;
e7ddee903   Jeff Layton   cifs: disable sha...
1703
1704
1705
  	task = xchg(&server->tsk, NULL);
  	if (task)
  		force_sig(SIGKILL, task);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1706
  }
63c038c29   Jeff Layton   cifs: move alloca...
1707
1708
1709
1710
  static struct TCP_Server_Info *
  cifs_get_tcp_session(struct smb_vol *volume_info)
  {
  	struct TCP_Server_Info *tcp_ses = NULL;
a9ac49d30   Jeff Layton   cifs: make sure w...
1711
  	struct sockaddr_storage addr;
63c038c29   Jeff Layton   cifs: move alloca...
1712
1713
1714
  	struct sockaddr_in *sin_server = (struct sockaddr_in *) &addr;
  	struct sockaddr_in6 *sin_server6 = (struct sockaddr_in6 *) &addr;
  	int rc;
a9ac49d30   Jeff Layton   cifs: make sure w...
1715
  	memset(&addr, 0, sizeof(struct sockaddr_storage));
63c038c29   Jeff Layton   cifs: move alloca...
1716

b6b38f704   Joe Perches   [CIFS] Neaten cER...
1717
  	cFYI(1, "UNC: %s ip: %s", volume_info->UNC, volume_info->UNCip);
63c038c29   Jeff Layton   cifs: move alloca...
1718

1e68b2b27   Jeff Layton   cifs: add new rou...
1719
  	if (volume_info->UNCip && volume_info->UNC) {
50d971602   Jeff Layton   cifs: set the por...
1720
1721
  		rc = cifs_fill_sockaddr((struct sockaddr *)&addr,
  					volume_info->UNCip,
67b7626a0   David Howells   CIFS: Make cifs_c...
1722
  					strlen(volume_info->UNCip),
50d971602   Jeff Layton   cifs: set the por...
1723
  					volume_info->port);
1e68b2b27   Jeff Layton   cifs: add new rou...
1724
  		if (!rc) {
63c038c29   Jeff Layton   cifs: move alloca...
1725
1726
1727
1728
  			/* we failed translating address */
  			rc = -EINVAL;
  			goto out_err;
  		}
63c038c29   Jeff Layton   cifs: move alloca...
1729
1730
1731
  	} else if (volume_info->UNCip) {
  		/* BB using ip addr as tcp_ses name to connect to the
  		   DFS root below */
b6b38f704   Joe Perches   [CIFS] Neaten cER...
1732
  		cERROR(1, "Connecting to DFS root not implemented yet");
63c038c29   Jeff Layton   cifs: move alloca...
1733
1734
1735
  		rc = -EINVAL;
  		goto out_err;
  	} else /* which tcp_sess DFS root would we conect to */ {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
1736
1737
  		cERROR(1, "CIFS mount error: No UNC path (e.g. -o "
  			"unc=//192.168.1.100/public) specified");
63c038c29   Jeff Layton   cifs: move alloca...
1738
1739
1740
1741
1742
  		rc = -EINVAL;
  		goto out_err;
  	}
  
  	/* see if we already have a matching tcp_ses */
daf5b0b6f   Jeff Layton   cifs: match secTy...
1743
  	tcp_ses = cifs_find_tcp_session((struct sockaddr *)&addr, volume_info);
63c038c29   Jeff Layton   cifs: move alloca...
1744
1745
1746
1747
1748
1749
1750
1751
  	if (tcp_ses)
  		return tcp_ses;
  
  	tcp_ses = kzalloc(sizeof(struct TCP_Server_Info), GFP_KERNEL);
  	if (!tcp_ses) {
  		rc = -ENOMEM;
  		goto out_err;
  	}
d2b915210   Shirish Pargaonkar   NTLM auth and sig...
1752
1753
1754
1755
1756
  	rc = cifs_crypto_shash_allocate(tcp_ses);
  	if (rc) {
  		cERROR(1, "could not setup hash structures rc %d", rc);
  		goto out_err;
  	}
f1d0c9986   Rob Landley   Make CIFS mount w...
1757
  	cifs_set_net_ns(tcp_ses, get_net(current->nsproxy->net_ns));
63c038c29   Jeff Layton   cifs: move alloca...
1758
1759
1760
  	tcp_ses->hostname = extract_hostname(volume_info->UNC);
  	if (IS_ERR(tcp_ses->hostname)) {
  		rc = PTR_ERR(tcp_ses->hostname);
f7c5445a9   Shirish Pargaonkar   NTLM auth and sig...
1761
  		goto out_err_crypto_release;
63c038c29   Jeff Layton   cifs: move alloca...
1762
1763
1764
1765
  	}
  
  	tcp_ses->noblocksnd = volume_info->noblocksnd;
  	tcp_ses->noautotune = volume_info->noautotune;
6a5fa2362   Steve French   [CIFS] Add suppor...
1766
  	tcp_ses->tcp_nodelay = volume_info->sockopt_tcp_nodelay;
63c038c29   Jeff Layton   cifs: move alloca...
1767
1768
1769
1770
1771
1772
1773
1774
1775
  	atomic_set(&tcp_ses->inFlight, 0);
  	init_waitqueue_head(&tcp_ses->response_q);
  	init_waitqueue_head(&tcp_ses->request_q);
  	INIT_LIST_HEAD(&tcp_ses->pending_mid_q);
  	mutex_init(&tcp_ses->srv_mutex);
  	memcpy(tcp_ses->workstation_RFC1001_name,
  		volume_info->source_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL);
  	memcpy(tcp_ses->server_RFC1001_name,
  		volume_info->target_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL);
5d0d28824   Shirish Pargaonkar   NTLM authenticati...
1776
  	tcp_ses->session_estab = false;
63c038c29   Jeff Layton   cifs: move alloca...
1777
  	tcp_ses->sequence_number = 0;
fda359436   Steve French   [CIFS] cifs: reco...
1778
  	tcp_ses->lstrp = jiffies;
63c038c29   Jeff Layton   cifs: move alloca...
1779
1780
  	INIT_LIST_HEAD(&tcp_ses->tcp_ses_list);
  	INIT_LIST_HEAD(&tcp_ses->smb_ses_list);
c74093b69   Jeff Layton   cifs: set up recu...
1781
  	INIT_DELAYED_WORK(&tcp_ses->echo, cifs_echo_request);
63c038c29   Jeff Layton   cifs: move alloca...
1782
1783
1784
1785
1786
1787
1788
  
  	/*
  	 * at this point we are the only ones with the pointer
  	 * to the struct since the kernel thread not created yet
  	 * no need to spinlock this init of tcpStatus or srv_count
  	 */
  	tcp_ses->tcpStatus = CifsNew;
3eb9a8893   Ben Greear   cifs: Allow bindi...
1789
1790
  	memcpy(&tcp_ses->srcaddr, &volume_info->srcaddr,
  	       sizeof(tcp_ses->srcaddr));
63c038c29   Jeff Layton   cifs: move alloca...
1791
  	++tcp_ses->srv_count;
a9ac49d30   Jeff Layton   cifs: make sure w...
1792
  	if (addr.ss_family == AF_INET6) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
1793
  		cFYI(1, "attempting ipv6 connect");
63c038c29   Jeff Layton   cifs: move alloca...
1794
1795
  		/* BB should we allow ipv6 on port 139? */
  		/* other OS never observed in Wild doing 139 with v6 */
a9f1b85e5   Pavel Shilovsky   CIFS: Simplify ip...
1796
1797
1798
1799
1800
1801
1802
  		memcpy(&tcp_ses->dstaddr, sin_server6,
  		       sizeof(struct sockaddr_in6));
  	} else
  		memcpy(&tcp_ses->dstaddr, sin_server,
  		       sizeof(struct sockaddr_in));
  
  	rc = ip_connect(tcp_ses);
63c038c29   Jeff Layton   cifs: move alloca...
1803
  	if (rc < 0) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
1804
  		cERROR(1, "Error connecting to socket. Aborting operation");
f7c5445a9   Shirish Pargaonkar   NTLM auth and sig...
1805
  		goto out_err_crypto_release;
63c038c29   Jeff Layton   cifs: move alloca...
1806
1807
1808
1809
1810
1811
1812
  	}
  
  	/*
  	 * since we're in a cifs function already, we know that
  	 * this will succeed. No need for try_module_get().
  	 */
  	__module_get(THIS_MODULE);
7c97c200e   Al Viro   cifs: fix the typ...
1813
  	tcp_ses->tsk = kthread_run(cifs_demultiplex_thread,
63c038c29   Jeff Layton   cifs: move alloca...
1814
1815
1816
  				  tcp_ses, "cifsd");
  	if (IS_ERR(tcp_ses->tsk)) {
  		rc = PTR_ERR(tcp_ses->tsk);
b6b38f704   Joe Perches   [CIFS] Neaten cER...
1817
  		cERROR(1, "error %d create cifsd thread", rc);
63c038c29   Jeff Layton   cifs: move alloca...
1818
  		module_put(THIS_MODULE);
f7c5445a9   Shirish Pargaonkar   NTLM auth and sig...
1819
  		goto out_err_crypto_release;
63c038c29   Jeff Layton   cifs: move alloca...
1820
  	}
fd88ce931   Steve French   [CIFS] cifs: clar...
1821
  	tcp_ses->tcpStatus = CifsNeedNegotiate;
63c038c29   Jeff Layton   cifs: move alloca...
1822
1823
  
  	/* thread spawned, put it on the list */
3f9bcca78   Suresh Jayaraman   cifs: convert cif...
1824
  	spin_lock(&cifs_tcp_ses_lock);
63c038c29   Jeff Layton   cifs: move alloca...
1825
  	list_add(&tcp_ses->tcp_ses_list, &cifs_tcp_ses_list);
3f9bcca78   Suresh Jayaraman   cifs: convert cif...
1826
  	spin_unlock(&cifs_tcp_ses_lock);
63c038c29   Jeff Layton   cifs: move alloca...
1827

488f1d2d6   Suresh Jayaraman   cifs: define serv...
1828
  	cifs_fscache_get_client_cookie(tcp_ses);
c74093b69   Jeff Layton   cifs: set up recu...
1829
1830
  	/* queue echo request delayed work */
  	queue_delayed_work(system_nrt_wq, &tcp_ses->echo, SMB_ECHO_INTERVAL);
63c038c29   Jeff Layton   cifs: move alloca...
1831
  	return tcp_ses;
f7c5445a9   Shirish Pargaonkar   NTLM auth and sig...
1832
  out_err_crypto_release:
d2b915210   Shirish Pargaonkar   NTLM auth and sig...
1833
  	cifs_crypto_shash_release(tcp_ses);
f1d0c9986   Rob Landley   Make CIFS mount w...
1834
  	put_net(cifs_net_ns(tcp_ses));
63c038c29   Jeff Layton   cifs: move alloca...
1835
1836
  out_err:
  	if (tcp_ses) {
8347a5cdd   Steve French   [CIFS] Fixing to ...
1837
1838
  		if (!IS_ERR(tcp_ses->hostname))
  			kfree(tcp_ses->hostname);
63c038c29   Jeff Layton   cifs: move alloca...
1839
1840
1841
1842
1843
1844
  		if (tcp_ses->ssocket)
  			sock_release(tcp_ses->ssocket);
  		kfree(tcp_ses);
  	}
  	return ERR_PTR(rc);
  }
96daf2b09   Steve French   [CIFS] Rename thr...
1845
  static int match_session(struct cifs_ses *ses, struct smb_vol *vol)
37bb04e5a   Pavel Shilovsky   CIFS: Simplify co...
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
  {
  	switch (ses->server->secType) {
  	case Kerberos:
  		if (vol->cred_uid != ses->cred_uid)
  			return 0;
  		break;
  	default:
  		/* anything else takes username/password */
  		if (ses->user_name == NULL)
  			return 0;
  		if (strncmp(ses->user_name, vol->username,
  			    MAX_USERNAME_SIZE))
  			return 0;
  		if (strlen(vol->username) != 0 &&
  		    ses->password != NULL &&
  		    strncmp(ses->password,
  			    vol->password ? vol->password : "",
  			    MAX_PASSWORD_SIZE))
  			return 0;
  	}
  	return 1;
  }
96daf2b09   Steve French   [CIFS] Rename thr...
1868
  static struct cifs_ses *
4ff67b720   Jeff Layton   cifs: clean up ci...
1869
  cifs_find_smb_ses(struct TCP_Server_Info *server, struct smb_vol *vol)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1870
  {
96daf2b09   Steve French   [CIFS] Rename thr...
1871
  	struct cifs_ses *ses;
dea570e08   Steve French   [CIFS] Remove ove...
1872

3f9bcca78   Suresh Jayaraman   cifs: convert cif...
1873
  	spin_lock(&cifs_tcp_ses_lock);
4ff67b720   Jeff Layton   cifs: clean up ci...
1874
  	list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
37bb04e5a   Pavel Shilovsky   CIFS: Simplify co...
1875
1876
  		if (!match_session(ses, vol))
  			continue;
14fbf50d6   Jeff Layton   cifs: reinstate s...
1877
  		++ses->ses_count;
3f9bcca78   Suresh Jayaraman   cifs: convert cif...
1878
  		spin_unlock(&cifs_tcp_ses_lock);
14fbf50d6   Jeff Layton   cifs: reinstate s...
1879
1880
  		return ses;
  	}
3f9bcca78   Suresh Jayaraman   cifs: convert cif...
1881
  	spin_unlock(&cifs_tcp_ses_lock);
14fbf50d6   Jeff Layton   cifs: reinstate s...
1882
1883
  	return NULL;
  }
dea570e08   Steve French   [CIFS] Remove ove...
1884

14fbf50d6   Jeff Layton   cifs: reinstate s...
1885
  static void
96daf2b09   Steve French   [CIFS] Rename thr...
1886
  cifs_put_smb_ses(struct cifs_ses *ses)
14fbf50d6   Jeff Layton   cifs: reinstate s...
1887
1888
1889
  {
  	int xid;
  	struct TCP_Server_Info *server = ses->server;
dea570e08   Steve French   [CIFS] Remove ove...
1890

36988c76f   Jeff Layton   cifs: move SMB se...
1891
1892
  	cFYI(1, "%s: ses_count=%d
  ", __func__, ses->ses_count);
3f9bcca78   Suresh Jayaraman   cifs: convert cif...
1893
  	spin_lock(&cifs_tcp_ses_lock);
14fbf50d6   Jeff Layton   cifs: reinstate s...
1894
  	if (--ses->ses_count > 0) {
3f9bcca78   Suresh Jayaraman   cifs: convert cif...
1895
  		spin_unlock(&cifs_tcp_ses_lock);
14fbf50d6   Jeff Layton   cifs: reinstate s...
1896
1897
  		return;
  	}
dea570e08   Steve French   [CIFS] Remove ove...
1898

14fbf50d6   Jeff Layton   cifs: reinstate s...
1899
  	list_del_init(&ses->smb_ses_list);
3f9bcca78   Suresh Jayaraman   cifs: convert cif...
1900
  	spin_unlock(&cifs_tcp_ses_lock);
dea570e08   Steve French   [CIFS] Remove ove...
1901

14fbf50d6   Jeff Layton   cifs: reinstate s...
1902
1903
1904
1905
1906
1907
1908
1909
  	if (ses->status == CifsGood) {
  		xid = GetXid();
  		CIFSSMBLogoff(xid, ses);
  		_FreeXid(xid);
  	}
  	sesInfoFree(ses);
  	cifs_put_tcp_session(server);
  }
dea570e08   Steve French   [CIFS] Remove ove...
1910

d9b942013   Steve French   [CIFS] Warn on re...
1911
  static bool warned_on_ntlm;  /* globals init to false automatically */
96daf2b09   Steve French   [CIFS] Rename thr...
1912
  static struct cifs_ses *
36988c76f   Jeff Layton   cifs: move SMB se...
1913
1914
1915
  cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
  {
  	int rc = -ENOMEM, xid;
96daf2b09   Steve French   [CIFS] Rename thr...
1916
  	struct cifs_ses *ses;
a9f1b85e5   Pavel Shilovsky   CIFS: Simplify ip...
1917
1918
  	struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr;
  	struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr;
36988c76f   Jeff Layton   cifs: move SMB se...
1919
1920
  
  	xid = GetXid();
4ff67b720   Jeff Layton   cifs: clean up ci...
1921
  	ses = cifs_find_smb_ses(server, volume_info);
36988c76f   Jeff Layton   cifs: move SMB se...
1922
1923
  	if (ses) {
  		cFYI(1, "Existing smb sess found (status=%d)", ses->status);
36988c76f   Jeff Layton   cifs: move SMB se...
1924
  		mutex_lock(&ses->session_mutex);
198b56827   Jeff Layton   cifs: break negot...
1925
1926
1927
1928
1929
1930
1931
1932
  		rc = cifs_negotiate_protocol(xid, ses);
  		if (rc) {
  			mutex_unlock(&ses->session_mutex);
  			/* problem -- put our ses reference */
  			cifs_put_smb_ses(ses);
  			FreeXid(xid);
  			return ERR_PTR(rc);
  		}
36988c76f   Jeff Layton   cifs: move SMB se...
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
  		if (ses->need_reconnect) {
  			cFYI(1, "Session needs reconnect");
  			rc = cifs_setup_session(xid, ses,
  						volume_info->local_nls);
  			if (rc) {
  				mutex_unlock(&ses->session_mutex);
  				/* problem -- put our reference */
  				cifs_put_smb_ses(ses);
  				FreeXid(xid);
  				return ERR_PTR(rc);
  			}
  		}
  		mutex_unlock(&ses->session_mutex);
460cf3411   Jeff Layton   cifs: fix potenti...
1946
1947
1948
  
  		/* existing SMB ses has a server reference already */
  		cifs_put_tcp_session(server);
36988c76f   Jeff Layton   cifs: move SMB se...
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
  		FreeXid(xid);
  		return ses;
  	}
  
  	cFYI(1, "Existing smb sess not found");
  	ses = sesInfoAlloc();
  	if (ses == NULL)
  		goto get_ses_fail;
  
  	/* new SMB session uses our server ref */
  	ses->server = server;
a9f1b85e5   Pavel Shilovsky   CIFS: Simplify ip...
1960
1961
  	if (server->dstaddr.ss_family == AF_INET6)
  		sprintf(ses->serverName, "%pI6", &addr6->sin6_addr);
36988c76f   Jeff Layton   cifs: move SMB se...
1962
  	else
a9f1b85e5   Pavel Shilovsky   CIFS: Simplify ip...
1963
  		sprintf(ses->serverName, "%pI4", &addr->sin_addr);
36988c76f   Jeff Layton   cifs: move SMB se...
1964

8727c8a85   Steve French   Allow user names ...
1965
1966
1967
1968
1969
  	if (volume_info->username) {
  		ses->user_name = kstrdup(volume_info->username, GFP_KERNEL);
  		if (!ses->user_name)
  			goto get_ses_fail;
  	}
36988c76f   Jeff Layton   cifs: move SMB se...
1970
1971
1972
1973
1974
1975
1976
1977
  
  	/* volume_info->password freed at unmount */
  	if (volume_info->password) {
  		ses->password = kstrdup(volume_info->password, GFP_KERNEL);
  		if (!ses->password)
  			goto get_ses_fail;
  	}
  	if (volume_info->domainname) {
d3686d54c   Shirish Pargaonkar   cifs: Cleanup and...
1978
1979
1980
  		ses->domainName = kstrdup(volume_info->domainname, GFP_KERNEL);
  		if (!ses->domainName)
  			goto get_ses_fail;
36988c76f   Jeff Layton   cifs: move SMB se...
1981
  	}
3e4b3e1f6   Jeff Layton   cifs: add separat...
1982
  	ses->cred_uid = volume_info->cred_uid;
36988c76f   Jeff Layton   cifs: move SMB se...
1983
  	ses->linux_uid = volume_info->linux_uid;
d9b942013   Steve French   [CIFS] Warn on re...
1984
1985
1986
1987
1988
1989
1990
  
  	/* ntlmv2 is much stronger than ntlm security, and has been broadly
  	supported for many years, time to update default security mechanism */
  	if ((volume_info->secFlg == 0) && warned_on_ntlm == false) {
  		warned_on_ntlm = true;
  		cERROR(1, "default security mechanism requested.  The default "
  			"security mechanism will be upgraded from ntlm to "
9d1e397b7   Steve French   [CIFS] Fix first ...
1991
  			"ntlmv2 in kernel release 3.2");
d9b942013   Steve French   [CIFS] Warn on re...
1992
  	}
36988c76f   Jeff Layton   cifs: move SMB se...
1993
1994
1995
  	ses->overrideSecFlg = volume_info->secFlg;
  
  	mutex_lock(&ses->session_mutex);
198b56827   Jeff Layton   cifs: break negot...
1996
1997
1998
  	rc = cifs_negotiate_protocol(xid, ses);
  	if (!rc)
  		rc = cifs_setup_session(xid, ses, volume_info->local_nls);
36988c76f   Jeff Layton   cifs: move SMB se...
1999
  	mutex_unlock(&ses->session_mutex);
c8e56f1f4   Steve French   Revert "[CIFS] Fi...
2000
  	if (rc)
36988c76f   Jeff Layton   cifs: move SMB se...
2001
2002
2003
  		goto get_ses_fail;
  
  	/* success, put it on the list */
3f9bcca78   Suresh Jayaraman   cifs: convert cif...
2004
  	spin_lock(&cifs_tcp_ses_lock);
36988c76f   Jeff Layton   cifs: move SMB se...
2005
  	list_add(&ses->smb_ses_list, &server->smb_ses_list);
3f9bcca78   Suresh Jayaraman   cifs: convert cif...
2006
  	spin_unlock(&cifs_tcp_ses_lock);
36988c76f   Jeff Layton   cifs: move SMB se...
2007
2008
2009
2010
2011
2012
2013
2014
2015
  
  	FreeXid(xid);
  	return ses;
  
  get_ses_fail:
  	sesInfoFree(ses);
  	FreeXid(xid);
  	return ERR_PTR(rc);
  }
96daf2b09   Steve French   [CIFS] Rename thr...
2016
  static int match_tcon(struct cifs_tcon *tcon, const char *unc)
37bb04e5a   Pavel Shilovsky   CIFS: Simplify co...
2017
2018
2019
2020
2021
2022
2023
  {
  	if (tcon->tidStatus == CifsExiting)
  		return 0;
  	if (strncmp(tcon->treeName, unc, MAX_TREE_SIZE))
  		return 0;
  	return 1;
  }
96daf2b09   Steve French   [CIFS] Rename thr...
2024
2025
  static struct cifs_tcon *
  cifs_find_tcon(struct cifs_ses *ses, const char *unc)
f1987b44f   Jeff Layton   cifs: reinstate s...
2026
2027
  {
  	struct list_head *tmp;
96daf2b09   Steve French   [CIFS] Rename thr...
2028
  	struct cifs_tcon *tcon;
f1987b44f   Jeff Layton   cifs: reinstate s...
2029

3f9bcca78   Suresh Jayaraman   cifs: convert cif...
2030
  	spin_lock(&cifs_tcp_ses_lock);
f1987b44f   Jeff Layton   cifs: reinstate s...
2031
  	list_for_each(tmp, &ses->tcon_list) {
96daf2b09   Steve French   [CIFS] Rename thr...
2032
  		tcon = list_entry(tmp, struct cifs_tcon, tcon_list);
37bb04e5a   Pavel Shilovsky   CIFS: Simplify co...
2033
  		if (!match_tcon(tcon, unc))
f1987b44f   Jeff Layton   cifs: reinstate s...
2034
  			continue;
f1987b44f   Jeff Layton   cifs: reinstate s...
2035
  		++tcon->tc_count;
3f9bcca78   Suresh Jayaraman   cifs: convert cif...
2036
  		spin_unlock(&cifs_tcp_ses_lock);
dea570e08   Steve French   [CIFS] Remove ove...
2037
  		return tcon;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2038
  	}
3f9bcca78   Suresh Jayaraman   cifs: convert cif...
2039
  	spin_unlock(&cifs_tcp_ses_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2040
2041
  	return NULL;
  }
f1987b44f   Jeff Layton   cifs: reinstate s...
2042
  static void
96daf2b09   Steve French   [CIFS] Rename thr...
2043
  cifs_put_tcon(struct cifs_tcon *tcon)
f1987b44f   Jeff Layton   cifs: reinstate s...
2044
2045
  {
  	int xid;
96daf2b09   Steve French   [CIFS] Rename thr...
2046
  	struct cifs_ses *ses = tcon->ses;
f1987b44f   Jeff Layton   cifs: reinstate s...
2047

d00c28de5   Jeff Layton   cifs: move tcon f...
2048
2049
  	cFYI(1, "%s: tc_count=%d
  ", __func__, tcon->tc_count);
3f9bcca78   Suresh Jayaraman   cifs: convert cif...
2050
  	spin_lock(&cifs_tcp_ses_lock);
f1987b44f   Jeff Layton   cifs: reinstate s...
2051
  	if (--tcon->tc_count > 0) {
3f9bcca78   Suresh Jayaraman   cifs: convert cif...
2052
  		spin_unlock(&cifs_tcp_ses_lock);
f1987b44f   Jeff Layton   cifs: reinstate s...
2053
2054
2055
2056
  		return;
  	}
  
  	list_del_init(&tcon->tcon_list);
3f9bcca78   Suresh Jayaraman   cifs: convert cif...
2057
  	spin_unlock(&cifs_tcp_ses_lock);
f1987b44f   Jeff Layton   cifs: reinstate s...
2058
2059
2060
2061
  
  	xid = GetXid();
  	CIFSSMBTDis(xid, tcon);
  	_FreeXid(xid);
d03382ce9   Suresh Jayaraman   cifs: define supe...
2062
  	cifs_fscache_release_super_cookie(tcon);
9f841593f   Steve French   [CIFS] relinquish...
2063
  	tconInfoFree(tcon);
f1987b44f   Jeff Layton   cifs: reinstate s...
2064
2065
  	cifs_put_smb_ses(ses);
  }
96daf2b09   Steve French   [CIFS] Rename thr...
2066
2067
  static struct cifs_tcon *
  cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
d00c28de5   Jeff Layton   cifs: move tcon f...
2068
2069
  {
  	int rc, xid;
96daf2b09   Steve French   [CIFS] Rename thr...
2070
  	struct cifs_tcon *tcon;
d00c28de5   Jeff Layton   cifs: move tcon f...
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
  
  	tcon = cifs_find_tcon(ses, volume_info->UNC);
  	if (tcon) {
  		cFYI(1, "Found match on UNC path");
  		/* existing tcon already has a reference */
  		cifs_put_smb_ses(ses);
  		if (tcon->seal != volume_info->seal)
  			cERROR(1, "transport encryption setting "
  				   "conflicts with existing tid");
  		return tcon;
  	}
  
  	tcon = tconInfoAlloc();
  	if (tcon == NULL) {
  		rc = -ENOMEM;
  		goto out_fail;
  	}
  
  	tcon->ses = ses;
  	if (volume_info->password) {
  		tcon->password = kstrdup(volume_info->password, GFP_KERNEL);
  		if (!tcon->password) {
  			rc = -ENOMEM;
  			goto out_fail;
  		}
  	}
  
  	if (strchr(volume_info->UNC + 3, '\\') == NULL
  	    && strchr(volume_info->UNC + 3, '/') == NULL) {
  		cERROR(1, "Missing share name");
  		rc = -ENODEV;
  		goto out_fail;
  	}
  
  	/* BB Do we need to wrap session_mutex around
  	 * this TCon call and Unix SetFS as
  	 * we do on SessSetup and reconnect? */
  	xid = GetXid();
  	rc = CIFSTCon(xid, ses, volume_info->UNC, tcon, volume_info->local_nls);
  	FreeXid(xid);
  	cFYI(1, "CIFS Tcon rc = %d", rc);
  	if (rc)
  		goto out_fail;
  
  	if (volume_info->nodfs) {
  		tcon->Flags &= ~SMB_SHARE_IS_IN_DFS;
  		cFYI(1, "DFS disabled (%d)", tcon->Flags);
  	}
  	tcon->seal = volume_info->seal;
  	/* we can have only one retry value for a connection
  	   to a share so for resources mounted more than once
  	   to the same server share the last value passed in
  	   for the retry flag is used */
  	tcon->retry = volume_info->retry;
  	tcon->nocase = volume_info->nocase;
  	tcon->local_lease = volume_info->local_lease;
3f9bcca78   Suresh Jayaraman   cifs: convert cif...
2127
  	spin_lock(&cifs_tcp_ses_lock);
d00c28de5   Jeff Layton   cifs: move tcon f...
2128
  	list_add(&tcon->tcon_list, &ses->tcon_list);
3f9bcca78   Suresh Jayaraman   cifs: convert cif...
2129
  	spin_unlock(&cifs_tcp_ses_lock);
d00c28de5   Jeff Layton   cifs: move tcon f...
2130

d03382ce9   Suresh Jayaraman   cifs: define supe...
2131
  	cifs_fscache_get_super_cookie(tcon);
d00c28de5   Jeff Layton   cifs: move tcon f...
2132
2133
2134
2135
2136
2137
  	return tcon;
  
  out_fail:
  	tconInfoFree(tcon);
  	return ERR_PTR(rc);
  }
9d002df49   Jeff Layton   cifs: add routine...
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
  void
  cifs_put_tlink(struct tcon_link *tlink)
  {
  	if (!tlink || IS_ERR(tlink))
  		return;
  
  	if (!atomic_dec_and_test(&tlink->tl_count) ||
  	    test_bit(TCON_LINK_IN_TREE, &tlink->tl_flags)) {
  		tlink->tl_time = jiffies;
  		return;
  	}
  
  	if (!IS_ERR(tlink_tcon(tlink)))
  		cifs_put_tcon(tlink_tcon(tlink));
  	kfree(tlink);
  	return;
  }
d00c28de5   Jeff Layton   cifs: move tcon f...
2155

25c7f41e9   Pavel Shilovsky   CIFS: Migrate to ...
2156
  static inline struct tcon_link *
cd51875d5   Pavel Shilovsky   CIFS: Fix sparse ...
2157
2158
2159
2160
  cifs_sb_master_tlink(struct cifs_sb_info *cifs_sb)
  {
  	return cifs_sb->master_tlink;
  }
25c7f41e9   Pavel Shilovsky   CIFS: Migrate to ...
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
  
  static int
  compare_mount_options(struct super_block *sb, struct cifs_mnt_data *mnt_data)
  {
  	struct cifs_sb_info *old = CIFS_SB(sb);
  	struct cifs_sb_info *new = mnt_data->cifs_sb;
  
  	if ((sb->s_flags & CIFS_MS_MASK) != (mnt_data->flags & CIFS_MS_MASK))
  		return 0;
  
  	if ((old->mnt_cifs_flags & CIFS_MOUNT_MASK) !=
  	    (new->mnt_cifs_flags & CIFS_MOUNT_MASK))
  		return 0;
  
  	if (old->rsize != new->rsize)
  		return 0;
  
  	/*
  	 * We want to share sb only if we don't specify wsize or specified wsize
  	 * is greater or equal than existing one.
  	 */
  	if (new->wsize && new->wsize < old->wsize)
  		return 0;
  
  	if (old->mnt_uid != new->mnt_uid || old->mnt_gid != new->mnt_gid)
  		return 0;
  
  	if (old->mnt_file_mode != new->mnt_file_mode ||
  	    old->mnt_dir_mode != new->mnt_dir_mode)
  		return 0;
  
  	if (strcmp(old->local_nls->charset, new->local_nls->charset))
  		return 0;
  
  	if (old->actimeo != new->actimeo)
  		return 0;
  
  	return 1;
  }
  
  int
  cifs_match_super(struct super_block *sb, void *data)
  {
  	struct cifs_mnt_data *mnt_data = (struct cifs_mnt_data *)data;
  	struct smb_vol *volume_info;
  	struct cifs_sb_info *cifs_sb;
  	struct TCP_Server_Info *tcp_srv;
96daf2b09   Steve French   [CIFS] Rename thr...
2208
2209
  	struct cifs_ses *ses;
  	struct cifs_tcon *tcon;
25c7f41e9   Pavel Shilovsky   CIFS: Migrate to ...
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
  	struct tcon_link *tlink;
  	struct sockaddr_storage addr;
  	int rc = 0;
  
  	memset(&addr, 0, sizeof(struct sockaddr_storage));
  
  	spin_lock(&cifs_tcp_ses_lock);
  	cifs_sb = CIFS_SB(sb);
  	tlink = cifs_get_tlink(cifs_sb_master_tlink(cifs_sb));
  	if (IS_ERR(tlink)) {
  		spin_unlock(&cifs_tcp_ses_lock);
  		return rc;
  	}
  	tcon = tlink_tcon(tlink);
  	ses = tcon->ses;
  	tcp_srv = ses->server;
  
  	volume_info = mnt_data->vol;
  
  	if (!volume_info->UNCip || !volume_info->UNC)
  		goto out;
  
  	rc = cifs_fill_sockaddr((struct sockaddr *)&addr,
  				volume_info->UNCip,
  				strlen(volume_info->UNCip),
  				volume_info->port);
  	if (!rc)
  		goto out;
  
  	if (!match_server(tcp_srv, (struct sockaddr *)&addr, volume_info) ||
  	    !match_session(ses, volume_info) ||
  	    !match_tcon(tcon, volume_info->UNC)) {
  		rc = 0;
  		goto out;
  	}
  
  	rc = compare_mount_options(sb, mnt_data);
  out:
25c7f41e9   Pavel Shilovsky   CIFS: Migrate to ...
2248
  	spin_unlock(&cifs_tcp_ses_lock);
f484b5d00   Jeff Layton   cifs: drop spinlo...
2249
  	cifs_put_tlink(tlink);
25c7f41e9   Pavel Shilovsky   CIFS: Migrate to ...
2250
2251
  	return rc;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2252
  int
96daf2b09   Steve French   [CIFS] Rename thr...
2253
  get_dfs_path(int xid, struct cifs_ses *pSesInfo, const char *old_path,
50c2f7538   Steve French   [CIFS] whitespace...
2254
  	     const struct nls_table *nls_codepage, unsigned int *pnum_referrals,
366781c19   Steve French   [CIFS] DFS build ...
2255
  	     struct dfs_info3_param **preferrals, int remap)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2256
2257
2258
2259
2260
  {
  	char *temp_unc;
  	int rc = 0;
  
  	*pnum_referrals = 0;
366781c19   Steve French   [CIFS] DFS build ...
2261
  	*preferrals = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2262
2263
2264
  
  	if (pSesInfo->ipc_tid == 0) {
  		temp_unc = kmalloc(2 /* for slashes */ +
50c2f7538   Steve French   [CIFS] whitespace...
2265
2266
  			strnlen(pSesInfo->serverName,
  				SERVER_NAME_LEN_WITH_NULL * 2)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2267
2268
2269
2270
2271
2272
2273
2274
2275
  				 + 1 + 4 /* slash IPC$ */  + 2,
  				GFP_KERNEL);
  		if (temp_unc == NULL)
  			return -ENOMEM;
  		temp_unc[0] = '\\';
  		temp_unc[1] = '\\';
  		strcpy(temp_unc + 2, pSesInfo->serverName);
  		strcpy(temp_unc + 2 + strlen(pSesInfo->serverName), "\\IPC$");
  		rc = CIFSTCon(xid, pSesInfo, temp_unc, NULL, nls_codepage);
b6b38f704   Joe Perches   [CIFS] Neaten cER...
2276
  		cFYI(1, "CIFS Tcon rc = %d ipc_tid = %d", rc, pSesInfo->ipc_tid);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2277
2278
2279
  		kfree(temp_unc);
  	}
  	if (rc == 0)
c2cf07d59   Steve French   [CIFS] Finishup D...
2280
  		rc = CIFSGetDFSRefer(xid, pSesInfo, old_path, preferrals,
737b758c9   Steve French   [PATCH] cifs: cha...
2281
  				     pnum_referrals, nls_codepage, remap);
366781c19   Steve French   [CIFS] DFS build ...
2282
2283
  	/* BB map targetUNCs to dfs_info3 structures, here or
  		in CIFSGetDFSRefer BB */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2284
2285
2286
  
  	return rc;
  }
09e50d55a   Jeff Layton   lockdep: annotate...
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
  #ifdef CONFIG_DEBUG_LOCK_ALLOC
  static struct lock_class_key cifs_key[2];
  static struct lock_class_key cifs_slock_key[2];
  
  static inline void
  cifs_reclassify_socket4(struct socket *sock)
  {
  	struct sock *sk = sock->sk;
  	BUG_ON(sock_owned_by_user(sk));
  	sock_lock_init_class_and_name(sk, "slock-AF_INET-CIFS",
  		&cifs_slock_key[0], "sk_lock-AF_INET-CIFS", &cifs_key[0]);
  }
  
  static inline void
  cifs_reclassify_socket6(struct socket *sock)
  {
  	struct sock *sk = sock->sk;
  	BUG_ON(sock_owned_by_user(sk));
  	sock_lock_init_class_and_name(sk, "slock-AF_INET6-CIFS",
  		&cifs_slock_key[1], "sk_lock-AF_INET6-CIFS", &cifs_key[1]);
  }
  #else
  static inline void
  cifs_reclassify_socket4(struct socket *sock)
  {
  }
  
  static inline void
  cifs_reclassify_socket6(struct socket *sock)
  {
  }
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2319
  /* See RFC1001 section 14 on representation of Netbios names */
50c2f7538   Steve French   [CIFS] whitespace...
2320
  static void rfc1002mangle(char *target, char *source, unsigned int length)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2321
  {
50c2f7538   Steve French   [CIFS] whitespace...
2322
  	unsigned int i, j;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2323

50c2f7538   Steve French   [CIFS] whitespace...
2324
  	for (i = 0, j = 0; i < (length); i++) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2325
2326
2327
  		/* mask a nibble at a time and encode */
  		target[j] = 'A' + (0x0F & (source[i] >> 4));
  		target[j+1] = 'A' + (0x0F & source[i]);
50c2f7538   Steve French   [CIFS] whitespace...
2328
  		j += 2;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2329
2330
2331
  	}
  
  }
3eb9a8893   Ben Greear   cifs: Allow bindi...
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
  static int
  bind_socket(struct TCP_Server_Info *server)
  {
  	int rc = 0;
  	if (server->srcaddr.ss_family != AF_UNSPEC) {
  		/* Bind to the specified local IP address */
  		struct socket *socket = server->ssocket;
  		rc = socket->ops->bind(socket,
  				       (struct sockaddr *) &server->srcaddr,
  				       sizeof(server->srcaddr));
  		if (rc < 0) {
  			struct sockaddr_in *saddr4;
  			struct sockaddr_in6 *saddr6;
  			saddr4 = (struct sockaddr_in *)&server->srcaddr;
  			saddr6 = (struct sockaddr_in6 *)&server->srcaddr;
  			if (saddr6->sin6_family == AF_INET6)
  				cERROR(1, "cifs: "
  				       "Failed to bind to: %pI6c, error: %d
  ",
  				       &saddr6->sin6_addr, rc);
  			else
  				cERROR(1, "cifs: "
  				       "Failed to bind to: %pI4, error: %d
  ",
  				       &saddr4->sin_addr.s_addr, rc);
  		}
  	}
  	return rc;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2361
2362
  
  static int
a9f1b85e5   Pavel Shilovsky   CIFS: Simplify ip...
2363
  ip_rfc1001_connect(struct TCP_Server_Info *server)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2364
2365
  {
  	int rc = 0;
a9f1b85e5   Pavel Shilovsky   CIFS: Simplify ip...
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
  	/*
  	 * some servers require RFC1001 sessinit before sending
  	 * negprot - BB check reconnection in case where second
  	 * sessinit is sent but no second negprot
  	 */
  	struct rfc1002_session_packet *ses_init_buf;
  	struct smb_hdr *smb_buf;
  	ses_init_buf = kzalloc(sizeof(struct rfc1002_session_packet),
  			       GFP_KERNEL);
  	if (ses_init_buf) {
  		ses_init_buf->trailer.session_req.called_len = 32;
  
  		if (server->server_RFC1001_name &&
  		    server->server_RFC1001_name[0] != 0)
  			rfc1002mangle(ses_init_buf->trailer.
  				      session_req.called_name,
  				      server->server_RFC1001_name,
  				      RFC1001_NAME_LEN_WITH_NULL);
  		else
  			rfc1002mangle(ses_init_buf->trailer.
  				      session_req.called_name,
  				      DEFAULT_CIFS_CALLED_NAME,
  				      RFC1001_NAME_LEN_WITH_NULL);
  
  		ses_init_buf->trailer.session_req.calling_len = 32;
  
  		/*
  		 * calling name ends in null (byte 16) from old smb
  		 * convention.
  		 */
  		if (server->workstation_RFC1001_name &&
  		    server->workstation_RFC1001_name[0] != 0)
  			rfc1002mangle(ses_init_buf->trailer.
  				      session_req.calling_name,
  				      server->workstation_RFC1001_name,
  				      RFC1001_NAME_LEN_WITH_NULL);
  		else
  			rfc1002mangle(ses_init_buf->trailer.
  				      session_req.calling_name,
  				      "LINUX_CIFS_CLNT",
  				      RFC1001_NAME_LEN_WITH_NULL);
  
  		ses_init_buf->trailer.session_req.scope1 = 0;
  		ses_init_buf->trailer.session_req.scope2 = 0;
  		smb_buf = (struct smb_hdr *)ses_init_buf;
  
  		/* sizeof RFC1002_SESSION_REQUEST with no scope */
be8e3b004   Steve French   consistently use ...
2413
  		smb_buf->smb_buf_length = cpu_to_be32(0x81000044);
a9f1b85e5   Pavel Shilovsky   CIFS: Simplify ip...
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
  		rc = smb_send(server, smb_buf, 0x44);
  		kfree(ses_init_buf);
  		/*
  		 * RFC1001 layer in at least one server
  		 * requires very short break before negprot
  		 * presumably because not expecting negprot
  		 * to follow so fast.  This is a simple
  		 * solution that works without
  		 * complicating the code and causes no
  		 * significant slowing down on mount
  		 * for everyone else
  		 */
  		usleep_range(1000, 2000);
  	}
  	/*
  	 * else the negprot may still work without this
  	 * even though malloc failed
  	 */
  
  	return rc;
  }
  
  static int
  generic_ip_connect(struct TCP_Server_Info *server)
  {
  	int rc = 0;
6da979106   Steve French   Elminate sparse _...
2440
  	__be16 sport;
a9f1b85e5   Pavel Shilovsky   CIFS: Simplify ip...
2441
  	int slen, sfamily;
bcf4b1063   Jeff Layton   cifs: make ipv4_c...
2442
  	struct socket *socket = server->ssocket;
a9f1b85e5   Pavel Shilovsky   CIFS: Simplify ip...
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
  	struct sockaddr *saddr;
  
  	saddr = (struct sockaddr *) &server->dstaddr;
  
  	if (server->dstaddr.ss_family == AF_INET6) {
  		sport = ((struct sockaddr_in6 *) saddr)->sin6_port;
  		slen = sizeof(struct sockaddr_in6);
  		sfamily = AF_INET6;
  	} else {
  		sport = ((struct sockaddr_in *) saddr)->sin_port;
  		slen = sizeof(struct sockaddr_in);
  		sfamily = AF_INET;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2456

bcf4b1063   Jeff Layton   cifs: make ipv4_c...
2457
  	if (socket == NULL) {
f1d0c9986   Rob Landley   Make CIFS mount w...
2458
2459
  		rc = __sock_create(cifs_net_ns(server), sfamily, SOCK_STREAM,
  				   IPPROTO_TCP, &socket, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2460
  		if (rc < 0) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
2461
  			cERROR(1, "Error %d creating socket", rc);
a9f1b85e5   Pavel Shilovsky   CIFS: Simplify ip...
2462
  			server->ssocket = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2463
  			return rc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2464
  		}
bcf4b1063   Jeff Layton   cifs: make ipv4_c...
2465
2466
  
  		/* BB other socket options to set KEEPALIVE, NODELAY? */
b6b38f704   Joe Perches   [CIFS] Neaten cER...
2467
  		cFYI(1, "Socket created");
bcf4b1063   Jeff Layton   cifs: make ipv4_c...
2468
2469
  		server->ssocket = socket;
  		socket->sk->sk_allocation = GFP_NOFS;
a9f1b85e5   Pavel Shilovsky   CIFS: Simplify ip...
2470
2471
2472
2473
  		if (sfamily == AF_INET6)
  			cifs_reclassify_socket6(socket);
  		else
  			cifs_reclassify_socket4(socket);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2474
  	}
3eb9a8893   Ben Greear   cifs: Allow bindi...
2475
2476
2477
  	rc = bind_socket(server);
  	if (rc < 0)
  		return rc;
bcf4b1063   Jeff Layton   cifs: make ipv4_c...
2478
2479
  	/*
  	 * Eventually check for other socket options to change from
a9f1b85e5   Pavel Shilovsky   CIFS: Simplify ip...
2480
2481
  	 * the default. sock_setsockopt not used because it expects
  	 * user space buffer
bcf4b1063   Jeff Layton   cifs: make ipv4_c...
2482
2483
  	 */
  	socket->sk->sk_rcvtimeo = 7 * HZ;
da505c386   Steve French   [CIFS] Make socke...
2484
  	socket->sk->sk_sndtimeo = 5 * HZ;
edf1ae403   Steve French   [CIFS] Reduce num...
2485

b387eaeb6   Steve French   [CIFS] Do not shr...
2486
  	/* make the bufsizes depend on wsize/rsize and max requests */
bcf4b1063   Jeff Layton   cifs: make ipv4_c...
2487
2488
2489
2490
2491
  	if (server->noautotune) {
  		if (socket->sk->sk_sndbuf < (200 * 1024))
  			socket->sk->sk_sndbuf = 200 * 1024;
  		if (socket->sk->sk_rcvbuf < (140 * 1024))
  			socket->sk->sk_rcvbuf = 140 * 1024;
edf1ae403   Steve French   [CIFS] Reduce num...
2492
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2493

6a5fa2362   Steve French   [CIFS] Add suppor...
2494
  	if (server->tcp_nodelay) {
a9f1b85e5   Pavel Shilovsky   CIFS: Simplify ip...
2495
  		int val = 1;
6a5fa2362   Steve French   [CIFS] Add suppor...
2496
2497
2498
  		rc = kernel_setsockopt(socket, SOL_TCP, TCP_NODELAY,
  				(char *)&val, sizeof(val));
  		if (rc)
b6b38f704   Joe Perches   [CIFS] Neaten cER...
2499
  			cFYI(1, "set TCP_NODELAY socket option error %d", rc);
6a5fa2362   Steve French   [CIFS] Add suppor...
2500
  	}
b6b38f704   Joe Perches   [CIFS] Neaten cER...
2501
  	 cFYI(1, "sndbuf %d rcvbuf %d rcvtimeo 0x%lx",
bcf4b1063   Jeff Layton   cifs: make ipv4_c...
2502
  		 socket->sk->sk_sndbuf,
b6b38f704   Joe Perches   [CIFS] Neaten cER...
2503
  		 socket->sk->sk_rcvbuf, socket->sk->sk_rcvtimeo);
bcf4b1063   Jeff Layton   cifs: make ipv4_c...
2504

ee1b3ea9e   Jeff Layton   cifs: set socket ...
2505
2506
2507
2508
2509
2510
2511
  	rc = socket->ops->connect(socket, saddr, slen, 0);
  	if (rc < 0) {
  		cFYI(1, "Error %d connecting to server", rc);
  		sock_release(socket);
  		server->ssocket = NULL;
  		return rc;
  	}
a9f1b85e5   Pavel Shilovsky   CIFS: Simplify ip...
2512
2513
  	if (sport == htons(RFC1001_PORT))
  		rc = ip_rfc1001_connect(server);
50c2f7538   Steve French   [CIFS] whitespace...
2514

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2515
2516
2517
2518
  	return rc;
  }
  
  static int
a9f1b85e5   Pavel Shilovsky   CIFS: Simplify ip...
2519
  ip_connect(struct TCP_Server_Info *server)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2520
  {
6da979106   Steve French   Elminate sparse _...
2521
  	__be16 *sport;
a9f1b85e5   Pavel Shilovsky   CIFS: Simplify ip...
2522
2523
  	struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr;
  	struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2524

a9f1b85e5   Pavel Shilovsky   CIFS: Simplify ip...
2525
2526
2527
2528
  	if (server->dstaddr.ss_family == AF_INET6)
  		sport = &addr6->sin6_port;
  	else
  		sport = &addr->sin_port;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2529

a9f1b85e5   Pavel Shilovsky   CIFS: Simplify ip...
2530
2531
  	if (*sport == 0) {
  		int rc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2532

a9f1b85e5   Pavel Shilovsky   CIFS: Simplify ip...
2533
2534
  		/* try with 445 port at first */
  		*sport = htons(CIFS_PORT);
3eb9a8893   Ben Greear   cifs: Allow bindi...
2535

a9f1b85e5   Pavel Shilovsky   CIFS: Simplify ip...
2536
  		rc = generic_ip_connect(server);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2537
  		if (rc >= 0)
a9f1b85e5   Pavel Shilovsky   CIFS: Simplify ip...
2538
  			return rc;
6a5fa2362   Steve French   [CIFS] Add suppor...
2539

a9f1b85e5   Pavel Shilovsky   CIFS: Simplify ip...
2540
2541
  		/* if it failed, try with 139 port */
  		*sport = htons(RFC1001_PORT);
6a5fa2362   Steve French   [CIFS] Add suppor...
2542
  	}
a9f1b85e5   Pavel Shilovsky   CIFS: Simplify ip...
2543
  	return generic_ip_connect(server);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2544
  }
96daf2b09   Steve French   [CIFS] Rename thr...
2545
  void reset_cifs_unix_caps(int xid, struct cifs_tcon *tcon,
2c6292ae4   Al Viro   cifs: don't pass ...
2546
  			  struct cifs_sb_info *cifs_sb, struct smb_vol *vol_info)
8af189715   Steve French   [CIFS] on reconne...
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
  {
  	/* if we are reconnecting then should we check to see if
  	 * any requested capabilities changed locally e.g. via
  	 * remount but we can not do much about it here
  	 * if they have (even if we could detect it by the following)
  	 * Perhaps we could add a backpointer to array of sb from tcon
  	 * or if we change to make all sb to same share the same
  	 * sb as NFS - then we only have one backpointer to sb.
  	 * What if we wanted to mount the server share twice once with
  	 * and once without posixacls or posix paths? */
  	__u64 saved_cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
50c2f7538   Steve French   [CIFS] whitespace...
2558

c18c842b1   Steve French   [CIFS] Allow disa...
2559
2560
2561
  	if (vol_info && vol_info->no_linux_ext) {
  		tcon->fsUnixInfo.Capability = 0;
  		tcon->unix_ext = 0; /* Unix Extensions disabled */
b6b38f704   Joe Perches   [CIFS] Neaten cER...
2562
  		cFYI(1, "Linux protocol extensions disabled");
c18c842b1   Steve French   [CIFS] Allow disa...
2563
2564
2565
2566
2567
  		return;
  	} else if (vol_info)
  		tcon->unix_ext = 1; /* Unix Extensions supported */
  
  	if (tcon->unix_ext == 0) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
2568
  		cFYI(1, "Unix extensions disabled so not set on reconnect");
c18c842b1   Steve French   [CIFS] Allow disa...
2569
2570
  		return;
  	}
50c2f7538   Steve French   [CIFS] whitespace...
2571

fb8c4b14d   Steve French   [CIFS] whitespace...
2572
  	if (!CIFSSMBQFSUnixInfo(xid, tcon)) {
8af189715   Steve French   [CIFS] on reconne...
2573
  		__u64 cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
6848b7334   Steve French   [CIFS] When manda...
2574
  		cFYI(1, "unix caps which server supports %lld", cap);
8af189715   Steve French   [CIFS] on reconne...
2575
2576
  		/* check for reconnect case in which we do not
  		   want to change the mount behavior if we can avoid it */
fb8c4b14d   Steve French   [CIFS] whitespace...
2577
  		if (vol_info == NULL) {
50c2f7538   Steve French   [CIFS] whitespace...
2578
  			/* turn off POSIX ACL and PATHNAMES if not set
8af189715   Steve French   [CIFS] on reconne...
2579
2580
2581
  			   originally at mount time */
  			if ((saved_cap & CIFS_UNIX_POSIX_ACL_CAP) == 0)
  				cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
11b6d6450   Igor Mammedov   [CIFS] Only conve...
2582
2583
  			if ((saved_cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) {
  				if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
b6b38f704   Joe Perches   [CIFS] Neaten cER...
2584
  					cERROR(1, "POSIXPATH support change");
8af189715   Steve French   [CIFS] on reconne...
2585
  				cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
11b6d6450   Igor Mammedov   [CIFS] Only conve...
2586
  			} else if ((cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
2587
2588
  				cERROR(1, "possible reconnect error");
  				cERROR(1, "server disabled POSIX path support");
11b6d6450   Igor Mammedov   [CIFS] Only conve...
2589
  			}
8af189715   Steve French   [CIFS] on reconne...
2590
  		}
50c2f7538   Steve French   [CIFS] whitespace...
2591

6848b7334   Steve French   [CIFS] When manda...
2592
2593
  		if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)
  			cERROR(1, "per-share encryption not supported yet");
8af189715   Steve French   [CIFS] on reconne...
2594
  		cap &= CIFS_UNIX_CAP_MASK;
75865f8cc   Steve French   [CIFS] Add in som...
2595
  		if (vol_info && vol_info->no_psx_acl)
8af189715   Steve French   [CIFS] on reconne...
2596
  			cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
75865f8cc   Steve French   [CIFS] Add in som...
2597
  		else if (CIFS_UNIX_POSIX_ACL_CAP & cap) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
2598
  			cFYI(1, "negotiated posix acl support");
2c6292ae4   Al Viro   cifs: don't pass ...
2599
2600
2601
  			if (cifs_sb)
  				cifs_sb->mnt_cifs_flags |=
  					CIFS_MOUNT_POSIXACL;
8af189715   Steve French   [CIFS] on reconne...
2602
  		}
75865f8cc   Steve French   [CIFS] Add in som...
2603
  		if (vol_info && vol_info->posix_paths == 0)
8af189715   Steve French   [CIFS] on reconne...
2604
  			cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
75865f8cc   Steve French   [CIFS] Add in som...
2605
  		else if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
2606
  			cFYI(1, "negotiate posix pathnames");
2c6292ae4   Al Viro   cifs: don't pass ...
2607
2608
  			if (cifs_sb)
  				cifs_sb->mnt_cifs_flags |=
8af189715   Steve French   [CIFS] on reconne...
2609
2610
  					CIFS_MOUNT_POSIX_PATHS;
  		}
50c2f7538   Steve French   [CIFS] whitespace...
2611

2c6292ae4   Al Viro   cifs: don't pass ...
2612
  		if (cifs_sb && (cifs_sb->rsize > 127 * 1024)) {
75865f8cc   Steve French   [CIFS] Add in som...
2613
  			if ((cap & CIFS_UNIX_LARGE_READ_CAP) == 0) {
2c6292ae4   Al Viro   cifs: don't pass ...
2614
  				cifs_sb->rsize = 127 * 1024;
b6b38f704   Joe Perches   [CIFS] Neaten cER...
2615
  				cFYI(DBG2, "larger reads not supported by srv");
75865f8cc   Steve French   [CIFS] Add in som...
2616
2617
  			}
  		}
50c2f7538   Steve French   [CIFS] whitespace...
2618

b6b38f704   Joe Perches   [CIFS] Neaten cER...
2619
  		cFYI(1, "Negotiate caps 0x%x", (int)cap);
8af189715   Steve French   [CIFS] on reconne...
2620
  #ifdef CONFIG_CIFS_DEBUG2
75865f8cc   Steve French   [CIFS] Add in som...
2621
  		if (cap & CIFS_UNIX_FCNTL_CAP)
b6b38f704   Joe Perches   [CIFS] Neaten cER...
2622
  			cFYI(1, "FCNTL cap");
75865f8cc   Steve French   [CIFS] Add in som...
2623
  		if (cap & CIFS_UNIX_EXTATTR_CAP)
b6b38f704   Joe Perches   [CIFS] Neaten cER...
2624
  			cFYI(1, "EXTATTR cap");
75865f8cc   Steve French   [CIFS] Add in som...
2625
  		if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
b6b38f704   Joe Perches   [CIFS] Neaten cER...
2626
  			cFYI(1, "POSIX path cap");
75865f8cc   Steve French   [CIFS] Add in som...
2627
  		if (cap & CIFS_UNIX_XATTR_CAP)
b6b38f704   Joe Perches   [CIFS] Neaten cER...
2628
  			cFYI(1, "XATTR cap");
75865f8cc   Steve French   [CIFS] Add in som...
2629
  		if (cap & CIFS_UNIX_POSIX_ACL_CAP)
b6b38f704   Joe Perches   [CIFS] Neaten cER...
2630
  			cFYI(1, "POSIX ACL cap");
75865f8cc   Steve French   [CIFS] Add in som...
2631
  		if (cap & CIFS_UNIX_LARGE_READ_CAP)
b6b38f704   Joe Perches   [CIFS] Neaten cER...
2632
  			cFYI(1, "very large read cap");
75865f8cc   Steve French   [CIFS] Add in som...
2633
  		if (cap & CIFS_UNIX_LARGE_WRITE_CAP)
b6b38f704   Joe Perches   [CIFS] Neaten cER...
2634
  			cFYI(1, "very large write cap");
6848b7334   Steve French   [CIFS] When manda...
2635
2636
2637
2638
  		if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)
  			cFYI(1, "transport encryption cap");
  		if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)
  			cFYI(1, "mandatory transport encryption cap");
8af189715   Steve French   [CIFS] on reconne...
2639
2640
  #endif /* CIFS_DEBUG2 */
  		if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) {
442aa310f   Steve French   [CIFS] Support fo...
2641
  			if (vol_info == NULL) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
2642
  				cFYI(1, "resetting capabilities failed");
442aa310f   Steve French   [CIFS] Support fo...
2643
  			} else
b6b38f704   Joe Perches   [CIFS] Neaten cER...
2644
  				cERROR(1, "Negotiating Unix capabilities "
5a44b3190   Steve French   [CIFS] Add warnin...
2645
2646
2647
2648
2649
  					   "with the server failed.  Consider "
  					   "mounting with the Unix Extensions
  "
  					   "disabled, if problems are found, "
  					   "by specifying the nounix mount "
b6b38f704   Joe Perches   [CIFS] Neaten cER...
2650
  					   "option.");
5a44b3190   Steve French   [CIFS] Add warnin...
2651

8af189715   Steve French   [CIFS] on reconne...
2652
2653
2654
  		}
  	}
  }
724d9f1cf   Pavel Shilovsky   CIFS: Simplify mo...
2655
2656
  void cifs_setup_cifs_sb(struct smb_vol *pvolume_info,
  			struct cifs_sb_info *cifs_sb)
b1c8d2b42   Jeff Layton   cifs: handle the ...
2657
  {
2de970ff6   Jeff Layton   cifs: implement r...
2658
  	INIT_DELAYED_WORK(&cifs_sb->prune_tlinks, cifs_prune_tlinks);
2ced6f693   Al Viro   cifs: initialize ...
2659
2660
  	spin_lock_init(&cifs_sb->tlink_tree_lock);
  	cifs_sb->tlink_tree = RB_ROOT;
3b7952109   Steve French   [CIFS] Fix cifs r...
2661
  	if (pvolume_info->rsize > CIFSMaxBufSize) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
2662
2663
  		cERROR(1, "rsize %d too large, using MaxBufSize",
  			pvolume_info->rsize);
3b7952109   Steve French   [CIFS] Fix cifs r...
2664
2665
2666
2667
2668
2669
  		cifs_sb->rsize = CIFSMaxBufSize;
  	} else if ((pvolume_info->rsize) &&
  			(pvolume_info->rsize <= CIFSMaxBufSize))
  		cifs_sb->rsize = pvolume_info->rsize;
  	else /* default */
  		cifs_sb->rsize = CIFSMaxBufSize;
3b7952109   Steve French   [CIFS] Fix cifs r...
2670
2671
2672
  	if (cifs_sb->rsize < 2048) {
  		cifs_sb->rsize = 2048;
  		/* Windows ME may prefer this */
b6b38f704   Joe Perches   [CIFS] Neaten cER...
2673
  		cFYI(1, "readsize set to minimum: 2048");
3b7952109   Steve French   [CIFS] Fix cifs r...
2674
  	}
25c7f41e9   Pavel Shilovsky   CIFS: Migrate to ...
2675
2676
2677
2678
2679
2680
2681
  
  	/*
  	 * Temporarily set wsize for matching superblock. If we end up using
  	 * new sb then cifs_negotiate_wsize will later negotiate it downward
  	 * if needed.
  	 */
  	cifs_sb->wsize = pvolume_info->wsize;
3b7952109   Steve French   [CIFS] Fix cifs r...
2682
2683
2684
2685
  	cifs_sb->mnt_uid = pvolume_info->linux_uid;
  	cifs_sb->mnt_gid = pvolume_info->linux_gid;
  	cifs_sb->mnt_file_mode = pvolume_info->file_mode;
  	cifs_sb->mnt_dir_mode = pvolume_info->dir_mode;
b6b38f704   Joe Perches   [CIFS] Neaten cER...
2686
2687
  	cFYI(1, "file mode: 0x%x  dir mode: 0x%x",
  		cifs_sb->mnt_file_mode, cifs_sb->mnt_dir_mode);
3b7952109   Steve French   [CIFS] Fix cifs r...
2688

6d20e8406   Suresh Jayaraman   cifs: add attribu...
2689
  	cifs_sb->actimeo = pvolume_info->actimeo;
724d9f1cf   Pavel Shilovsky   CIFS: Simplify mo...
2690
  	cifs_sb->local_nls = pvolume_info->local_nls;
6d20e8406   Suresh Jayaraman   cifs: add attribu...
2691

3b7952109   Steve French   [CIFS] Fix cifs r...
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
  	if (pvolume_info->noperm)
  		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
  	if (pvolume_info->setuids)
  		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
  	if (pvolume_info->server_ino)
  		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
  	if (pvolume_info->remap)
  		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
  	if (pvolume_info->no_xattr)
  		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
  	if (pvolume_info->sfu_emul)
  		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL;
  	if (pvolume_info->nobrl)
  		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL;
be652445f   Steve French   [CIFS] Add new no...
2706
  	if (pvolume_info->nostrictsync)
4717bed68   Steve French   [CIFS] fix build ...
2707
  		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOSSYNC;
13a6e42af   Steve French   [CIFS] add mount ...
2708
2709
  	if (pvolume_info->mand_lock)
  		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOPOSIXBRL;
d4ffff1fa   Pavel Shilovsky   CIFS: Add rwpidfo...
2710
2711
  	if (pvolume_info->rwpidforward)
  		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_RWPIDFORWARD;
3b7952109   Steve French   [CIFS] Fix cifs r...
2712
2713
2714
2715
2716
2717
2718
2719
  	if (pvolume_info->cifs_acl)
  		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL;
  	if (pvolume_info->override_uid)
  		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_UID;
  	if (pvolume_info->override_gid)
  		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_GID;
  	if (pvolume_info->dynperm)
  		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DYNPERM;
fa1df75d4   Suresh Jayaraman   cifs: add mount o...
2720
2721
  	if (pvolume_info->fsc)
  		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_FSCACHE;
0eb8a132c   Jeff Layton   cifs: add "multiu...
2722
2723
2724
  	if (pvolume_info->multiuser)
  		cifs_sb->mnt_cifs_flags |= (CIFS_MOUNT_MULTIUSER |
  					    CIFS_MOUNT_NO_PERM);
d39454ffe   Pavel Shilovsky   CIFS: Add strictc...
2725
2726
  	if (pvolume_info->strict_io)
  		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_STRICT_IO;
3b7952109   Steve French   [CIFS] Fix cifs r...
2727
  	if (pvolume_info->direct_io) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
2728
  		cFYI(1, "mounting share using direct i/o");
3b7952109   Steve French   [CIFS] Fix cifs r...
2729
2730
  		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
  	}
736a33205   Stefan Metzmacher   cifs: add "mfsyml...
2731
2732
2733
2734
2735
2736
2737
2738
  	if (pvolume_info->mfsymlinks) {
  		if (pvolume_info->sfu_emul) {
  			cERROR(1,  "mount option mfsymlinks ignored if sfu "
  				   "mount option is used");
  		} else {
  			cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MF_SYMLINKS;
  		}
  	}
3b7952109   Steve French   [CIFS] Fix cifs r...
2739
2740
  
  	if ((pvolume_info->cifs_acl) && (pvolume_info->dynperm))
b6b38f704   Joe Perches   [CIFS] Neaten cER...
2741
2742
  		cERROR(1, "mount option dynperm ignored if cifsacl "
  			   "mount option supported");
b1c8d2b42   Jeff Layton   cifs: handle the ...
2743
  }
f7910cbd9   Jeff Layton   cifs: clean up ws...
2744
2745
  /*
   * When the server supports very large writes via POSIX extensions, we can
1190f6a06   Jeff Layton   cifs: fix wsize n...
2746
2747
   * allow up to 2^24-1, minus the size of a WRITE_AND_X header, not including
   * the RFC1001 length.
f7910cbd9   Jeff Layton   cifs: clean up ws...
2748
2749
   *
   * Note that this might make for "interesting" allocation problems during
1190f6a06   Jeff Layton   cifs: fix wsize n...
2750
2751
   * writeback however as we have to allocate an array of pointers for the
   * pages. A 16M write means ~32kb page array with PAGE_CACHE_SIZE == 4096.
f7910cbd9   Jeff Layton   cifs: clean up ws...
2752
   */
1190f6a06   Jeff Layton   cifs: fix wsize n...
2753
  #define CIFS_MAX_WSIZE ((1<<24) - 1 - sizeof(WRITE_REQ) + 4)
f7910cbd9   Jeff Layton   cifs: clean up ws...
2754
2755
  
  /*
1190f6a06   Jeff Layton   cifs: fix wsize n...
2756
2757
2758
   * When the server doesn't allow large posix writes, only allow a wsize of
   * 128k minus the size of the WRITE_AND_X header. That allows for a write up
   * to the maximum size described by RFC1002.
f7910cbd9   Jeff Layton   cifs: clean up ws...
2759
   */
1190f6a06   Jeff Layton   cifs: fix wsize n...
2760
  #define CIFS_MAX_RFC1002_WSIZE (128 * 1024 - sizeof(WRITE_REQ) + 4)
f7910cbd9   Jeff Layton   cifs: clean up ws...
2761
2762
2763
2764
2765
2766
2767
2768
2769
  
  /*
   * The default wsize is 1M. find_get_pages seems to return a maximum of 256
   * pages in a single call. With PAGE_CACHE_SIZE == 4k, this means we can fill
   * a single wsize request with a single call.
   */
  #define CIFS_DEFAULT_WSIZE (1024 * 1024)
  
  static unsigned int
96daf2b09   Steve French   [CIFS] Rename thr...
2770
  cifs_negotiate_wsize(struct cifs_tcon *tcon, struct smb_vol *pvolume_info)
f7910cbd9   Jeff Layton   cifs: clean up ws...
2771
2772
2773
2774
2775
2776
2777
2778
  {
  	__u64 unix_cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
  	struct TCP_Server_Info *server = tcon->ses->server;
  	unsigned int wsize = pvolume_info->wsize ? pvolume_info->wsize :
  				CIFS_DEFAULT_WSIZE;
  
  	/* can server support 24-bit write sizes? (via UNIX extensions) */
  	if (!tcon->unix_ext || !(unix_cap & CIFS_UNIX_LARGE_WRITE_CAP))
1190f6a06   Jeff Layton   cifs: fix wsize n...
2779
  		wsize = min_t(unsigned int, wsize, CIFS_MAX_RFC1002_WSIZE);
f7910cbd9   Jeff Layton   cifs: clean up ws...
2780

1190f6a06   Jeff Layton   cifs: fix wsize n...
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
  	/*
  	 * no CAP_LARGE_WRITE_X or is signing enabled without CAP_UNIX set?
  	 * Limit it to max buffer offered by the server, minus the size of the
  	 * WRITEX header, not including the 4 byte RFC1001 length.
  	 */
  	if (!(server->capabilities & CAP_LARGE_WRITE_X) ||
  	    (!(server->capabilities & CAP_UNIX) &&
  	     (server->sec_mode & (SECMODE_SIGN_ENABLED|SECMODE_SIGN_REQUIRED))))
  		wsize = min_t(unsigned int, wsize,
  				server->maxBuf - sizeof(WRITE_REQ) + 4);
f7910cbd9   Jeff Layton   cifs: clean up ws...
2791
2792
2793
2794
2795
2796
  
  	/* hard limit of CIFS_MAX_WSIZE */
  	wsize = min_t(unsigned int, wsize, CIFS_MAX_WSIZE);
  
  	return wsize;
  }
e4cce94c9   Igor Mammedov   [CIFS] Prevent OO...
2797
  static int
96daf2b09   Steve French   [CIFS] Rename thr...
2798
  is_path_accessible(int xid, struct cifs_tcon *tcon,
e4cce94c9   Igor Mammedov   [CIFS] Prevent OO...
2799
2800
2801
  		   struct cifs_sb_info *cifs_sb, const char *full_path)
  {
  	int rc;
e4cce94c9   Igor Mammedov   [CIFS] Prevent OO...
2802
  	FILE_ALL_INFO *pfile_info;
e4cce94c9   Igor Mammedov   [CIFS] Prevent OO...
2803
2804
2805
2806
2807
2808
2809
2810
  	pfile_info = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
  	if (pfile_info == NULL)
  		return -ENOMEM;
  
  	rc = CIFSSMBQPathInfo(xid, tcon, full_path, pfile_info,
  			      0 /* not legacy */, cifs_sb->local_nls,
  			      cifs_sb->mnt_cifs_flags &
  				CIFS_MOUNT_MAP_SPECIAL_CHR);
221d1d797   Jeff Layton   cifs: add fallbac...
2811
2812
2813
2814
2815
  
  	if (rc == -EOPNOTSUPP || rc == -EINVAL)
  		rc = SMBQueryInformation(xid, tcon, full_path, pfile_info,
  				cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
  				  CIFS_MOUNT_MAP_SPECIAL_CHR);
e4cce94c9   Igor Mammedov   [CIFS] Prevent OO...
2816
2817
2818
  	kfree(pfile_info);
  	return rc;
  }
b9bce2e9f   Jeff Layton   cifs: fix expand_...
2819
2820
  static void
  cleanup_volume_info_contents(struct smb_vol *volume_info)
1bfe73c25   Igor Mammedov   Remote DFS root s...
2821
  {
b946845a9   Sean Finney   cifs: cifs_parse_...
2822
  	kfree(volume_info->username);
1bfe73c25   Igor Mammedov   Remote DFS root s...
2823
2824
  	kzfree(volume_info->password);
  	kfree(volume_info->UNC);
13589c437   Steve French   [CIFS] possible m...
2825
2826
  	if (volume_info->UNCip != volume_info->UNC + 2)
  		kfree(volume_info->UNCip);
b946845a9   Sean Finney   cifs: cifs_parse_...
2827
2828
  	kfree(volume_info->domainname);
  	kfree(volume_info->iocharset);
1bfe73c25   Igor Mammedov   Remote DFS root s...
2829
  	kfree(volume_info->prepath);
b9bce2e9f   Jeff Layton   cifs: fix expand_...
2830
2831
2832
2833
2834
2835
2836
2837
  }
  
  void
  cifs_cleanup_volume_info(struct smb_vol *volume_info)
  {
  	if (!volume_info)
  		return;
  	cleanup_volume_info_contents(volume_info);
1bfe73c25   Igor Mammedov   Remote DFS root s...
2838
  	kfree(volume_info);
1bfe73c25   Igor Mammedov   Remote DFS root s...
2839
  }
b9bce2e9f   Jeff Layton   cifs: fix expand_...
2840

2d6d589d8   Steve French   [CIFS] remove som...
2841
  #ifdef CONFIG_CIFS_DFS_UPCALL
1bfe73c25   Igor Mammedov   Remote DFS root s...
2842
2843
2844
  /* build_path_to_root returns full path to root when
   * we do not have an exiting connection (tcon) */
  static char *
b2a0fa152   Jeff Layton   cifs: fix build_u...
2845
  build_unc_path_to_root(const struct smb_vol *vol,
1bfe73c25   Igor Mammedov   Remote DFS root s...
2846
2847
  		const struct cifs_sb_info *cifs_sb)
  {
b2a0fa152   Jeff Layton   cifs: fix build_u...
2848
2849
2850
  	char *full_path, *pos;
  	unsigned int pplen = vol->prepath ? strlen(vol->prepath) : 0;
  	unsigned int unc_len = strnlen(vol->UNC, MAX_TREE_SIZE + 1);
1bfe73c25   Igor Mammedov   Remote DFS root s...
2851

b2a0fa152   Jeff Layton   cifs: fix build_u...
2852
  	full_path = kmalloc(unc_len + pplen + 1, GFP_KERNEL);
1bfe73c25   Igor Mammedov   Remote DFS root s...
2853
2854
  	if (full_path == NULL)
  		return ERR_PTR(-ENOMEM);
b2a0fa152   Jeff Layton   cifs: fix build_u...
2855
2856
2857
2858
2859
2860
2861
2862
2863
  	strncpy(full_path, vol->UNC, unc_len);
  	pos = full_path + unc_len;
  
  	if (pplen) {
  		strncpy(pos, vol->prepath, pplen);
  		pos += pplen;
  	}
  
  	*pos = '\0'; /* add trailing null */
f87d39d95   Steve French   [CIFS] Migrate fr...
2864
  	convert_delimiter(full_path, CIFS_DIR_SEP(cifs_sb));
b2a0fa152   Jeff Layton   cifs: fix build_u...
2865
  	cFYI(1, "%s: full_path=%s", __func__, full_path);
1bfe73c25   Igor Mammedov   Remote DFS root s...
2866
2867
  	return full_path;
  }
dd6139458   Sean Finney   cifs: Extract DFS...
2868
2869
2870
2871
  
  /*
   * Perform a dfs referral query for a share and (optionally) prefix
   *
046462abc   Sean Finney   cifs: Simplify ha...
2872
2873
2874
   * If a referral is found, cifs_sb->mountdata will be (re-)allocated
   * to a string containing updated options for the submount.  Otherwise it
   * will be left untouched.
dd6139458   Sean Finney   cifs: Extract DFS...
2875
2876
2877
2878
2879
   *
   * Returns the rc from get_dfs_path to the caller, which can be used to
   * determine whether there were referrals.
   */
  static int
96daf2b09   Steve French   [CIFS] Rename thr...
2880
  expand_dfs_referral(int xid, struct cifs_ses *pSesInfo,
dd6139458   Sean Finney   cifs: Extract DFS...
2881
  		    struct smb_vol *volume_info, struct cifs_sb_info *cifs_sb,
046462abc   Sean Finney   cifs: Simplify ha...
2882
  		    int check_prefix)
dd6139458   Sean Finney   cifs: Extract DFS...
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
  {
  	int rc;
  	unsigned int num_referrals = 0;
  	struct dfs_info3_param *referrals = NULL;
  	char *full_path = NULL, *ref_path = NULL, *mdata = NULL;
  
  	full_path = build_unc_path_to_root(volume_info, cifs_sb);
  	if (IS_ERR(full_path))
  		return PTR_ERR(full_path);
  
  	/* For DFS paths, skip the first '\' of the UNC */
  	ref_path = check_prefix ? full_path + 1 : volume_info->UNC + 1;
  
  	rc = get_dfs_path(xid, pSesInfo , ref_path, cifs_sb->local_nls,
  			  &num_referrals, &referrals,
  			  cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
  
  	if (!rc && num_referrals > 0) {
  		char *fake_devname = NULL;
  
  		mdata = cifs_compose_mount_options(cifs_sb->mountdata,
  						   full_path + 1, referrals,
  						   &fake_devname);
  
  		free_dfs_info_array(referrals, num_referrals);
046462abc   Sean Finney   cifs: Simplify ha...
2908

dd6139458   Sean Finney   cifs: Extract DFS...
2909
2910
2911
  		if (IS_ERR(mdata)) {
  			rc = PTR_ERR(mdata);
  			mdata = NULL;
b9bce2e9f   Jeff Layton   cifs: fix expand_...
2912
2913
2914
2915
2916
  		} else {
  			cleanup_volume_info_contents(volume_info);
  			memset(volume_info, '\0', sizeof(*volume_info));
  			rc = cifs_setup_volume_info(volume_info, mdata,
  							fake_devname);
dd6139458   Sean Finney   cifs: Extract DFS...
2917
  		}
b9bce2e9f   Jeff Layton   cifs: fix expand_...
2918
2919
  		kfree(fake_devname);
  		kfree(cifs_sb->mountdata);
046462abc   Sean Finney   cifs: Simplify ha...
2920
  		cifs_sb->mountdata = mdata;
dd6139458   Sean Finney   cifs: Extract DFS...
2921
2922
2923
2924
  	}
  	kfree(full_path);
  	return rc;
  }
2d6d589d8   Steve French   [CIFS] remove som...
2925
  #endif
1bfe73c25   Igor Mammedov   Remote DFS root s...
2926

04db79b01   Jeff Layton   cifs: factor smb_...
2927
2928
2929
  static int
  cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data,
  			const char *devname)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2930
  {
724d9f1cf   Pavel Shilovsky   CIFS: Simplify mo...
2931
  	int rc = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2932

04db79b01   Jeff Layton   cifs: factor smb_...
2933
2934
  	if (cifs_parse_mount_options(mount_data, devname, volume_info))
  		return -EINVAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2935

7586b7658   Jeff Layton   cifs: don't decla...
2936
  	if (volume_info->nullauth) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
2937
  		cFYI(1, "null user");
446b23a75   Pavel Shilovsky   CIFS: Fix problem...
2938
  		volume_info->username = kzalloc(1, GFP_KERNEL);
04db79b01   Jeff Layton   cifs: factor smb_...
2939
2940
  		if (volume_info->username == NULL)
  			return -ENOMEM;
7586b7658   Jeff Layton   cifs: don't decla...
2941
  	} else if (volume_info->username) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2942
  		/* BB fixme parse for domain name here */
b6b38f704   Joe Perches   [CIFS] Neaten cER...
2943
  		cFYI(1, "Username: %s", volume_info->username);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2944
  	} else {
bf8206791   Steve French   [CIFS] Kerberos a...
2945
  		cifserror("No username specified");
50c2f7538   Steve French   [CIFS] whitespace...
2946
2947
  	/* In userspace mount helper we can get user name from alternate
  	   locations such as env variables and files on disk */
04db79b01   Jeff Layton   cifs: factor smb_...
2948
  		return -EINVAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2949
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2950
  	/* this is needed for ASCII cp to Unicode converts */
7586b7658   Jeff Layton   cifs: don't decla...
2951
  	if (volume_info->iocharset == NULL) {
a5fc4ce01   Jeff Layton   cifs: track local...
2952
2953
  		/* load_nls_default cannot return null */
  		volume_info->local_nls = load_nls_default();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2954
  	} else {
a5fc4ce01   Jeff Layton   cifs: track local...
2955
2956
  		volume_info->local_nls = load_nls(volume_info->iocharset);
  		if (volume_info->local_nls == NULL) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
2957
2958
  			cERROR(1, "CIFS mount error: iocharset %s not found",
  				 volume_info->iocharset);
04db79b01   Jeff Layton   cifs: factor smb_...
2959
  			return -ELIBACC;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2960
2961
  		}
  	}
724d9f1cf   Pavel Shilovsky   CIFS: Simplify mo...
2962

724d9f1cf   Pavel Shilovsky   CIFS: Simplify mo...
2963
2964
  	return rc;
  }
04db79b01   Jeff Layton   cifs: factor smb_...
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
  struct smb_vol *
  cifs_get_volume_info(char *mount_data, const char *devname)
  {
  	int rc;
  	struct smb_vol *volume_info;
  
  	volume_info = kzalloc(sizeof(struct smb_vol), GFP_KERNEL);
  	if (!volume_info)
  		return ERR_PTR(-ENOMEM);
  
  	rc = cifs_setup_volume_info(volume_info, mount_data, devname);
  	if (rc) {
  		cifs_cleanup_volume_info(volume_info);
  		volume_info = ERR_PTR(rc);
  	}
  
  	return volume_info;
  }
724d9f1cf   Pavel Shilovsky   CIFS: Simplify mo...
2983
  int
2c6292ae4   Al Viro   cifs: don't pass ...
2984
  cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *volume_info)
724d9f1cf   Pavel Shilovsky   CIFS: Simplify mo...
2985
2986
2987
  {
  	int rc = 0;
  	int xid;
96daf2b09   Steve French   [CIFS] Rename thr...
2988
2989
  	struct cifs_ses *pSesInfo;
  	struct cifs_tcon *tcon;
724d9f1cf   Pavel Shilovsky   CIFS: Simplify mo...
2990
2991
2992
2993
2994
  	struct TCP_Server_Info *srvTcp;
  	char   *full_path;
  	struct tcon_link *tlink;
  #ifdef CONFIG_CIFS_DFS_UPCALL
  	int referral_walks_count = 0;
20547490c   Jeff Layton   cifs: move bdi_se...
2995
  #endif
dd8544661   Al Viro   take bdi setup/de...
2996
2997
2998
2999
3000
3001
  
  	rc = bdi_setup_and_register(&cifs_sb->bdi, "cifs", BDI_CAP_MAP_COPY);
  	if (rc)
  		return rc;
  
  	cifs_sb->bdi.ra_pages = default_backing_dev_info.ra_pages;
20547490c   Jeff Layton   cifs: move bdi_se...
3002
  #ifdef CONFIG_CIFS_DFS_UPCALL
724d9f1cf   Pavel Shilovsky   CIFS: Simplify mo...
3003
3004
3005
3006
3007
3008
3009
  try_mount_again:
  	/* cleanup activities if we're chasing a referral */
  	if (referral_walks_count) {
  		if (tcon)
  			cifs_put_tcon(tcon);
  		else if (pSesInfo)
  			cifs_put_smb_ses(pSesInfo);
724d9f1cf   Pavel Shilovsky   CIFS: Simplify mo...
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
  		FreeXid(xid);
  	}
  #endif
  	tcon = NULL;
  	pSesInfo = NULL;
  	srvTcp = NULL;
  	full_path = NULL;
  	tlink = NULL;
  
  	xid = GetXid();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3020

63c038c29   Jeff Layton   cifs: move alloca...
3021
  	/* get a reference to a tcp session */
7586b7658   Jeff Layton   cifs: don't decla...
3022
  	srvTcp = cifs_get_tcp_session(volume_info);
63c038c29   Jeff Layton   cifs: move alloca...
3023
3024
  	if (IS_ERR(srvTcp)) {
  		rc = PTR_ERR(srvTcp);
dd8544661   Al Viro   take bdi setup/de...
3025
  		bdi_destroy(&cifs_sb->bdi);
63c038c29   Jeff Layton   cifs: move alloca...
3026
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3027
  	}
36988c76f   Jeff Layton   cifs: move SMB se...
3028
3029
3030
3031
3032
3033
  	/* get a reference to a SMB session */
  	pSesInfo = cifs_get_smb_ses(srvTcp, volume_info);
  	if (IS_ERR(pSesInfo)) {
  		rc = PTR_ERR(pSesInfo);
  		pSesInfo = NULL;
  		goto mount_fail_check;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3034
  	}
50c2f7538   Steve French   [CIFS] whitespace...
3035

d00c28de5   Jeff Layton   cifs: move tcon f...
3036
3037
3038
3039
3040
  	/* search for existing tcon to this server share */
  	tcon = cifs_get_tcon(pSesInfo, volume_info);
  	if (IS_ERR(tcon)) {
  		rc = PTR_ERR(tcon);
  		tcon = NULL;
1bfe73c25   Igor Mammedov   Remote DFS root s...
3041
  		goto remote_path_check;
d00c28de5   Jeff Layton   cifs: move tcon f...
3042
  	}
1bfe73c25   Igor Mammedov   Remote DFS root s...
3043

d82c2df54   Steve French   [CIFS] minor clea...
3044
  	/* tell server which Unix caps we support */
6848b7334   Steve French   [CIFS] When manda...
3045
  	if (tcon->ses->capabilities & CAP_UNIX) {
d82c2df54   Steve French   [CIFS] minor clea...
3046
3047
  		/* reset of caps checks mount to see if unix extensions
  		   disabled for just this mount */
2c6292ae4   Al Viro   cifs: don't pass ...
3048
  		reset_cifs_unix_caps(xid, tcon, cifs_sb, volume_info);
6848b7334   Steve French   [CIFS] When manda...
3049
3050
3051
3052
3053
3054
3055
  		if ((tcon->ses->server->tcpStatus == CifsNeedReconnect) &&
  		    (le64_to_cpu(tcon->fsUnixInfo.Capability) &
  		     CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)) {
  			rc = -EACCES;
  			goto mount_fail_check;
  		}
  	} else
d82c2df54   Steve French   [CIFS] minor clea...
3056
  		tcon->unix_ext = 0; /* server does not support them */
c18c842b1   Steve French   [CIFS] Allow disa...
3057

6848b7334   Steve French   [CIFS] When manda...
3058
3059
3060
3061
3062
  	/* do not care if following two calls succeed - informational */
  	if (!tcon->ipc) {
  		CIFSSMBQFSDeviceInfo(xid, tcon);
  		CIFSSMBQFSAttributeInfo(xid, tcon);
  	}
d82c2df54   Steve French   [CIFS] minor clea...
3063
3064
  	if ((tcon->unix_ext == 0) && (cifs_sb->rsize > (1024 * 127))) {
  		cifs_sb->rsize = 1024 * 127;
b6b38f704   Joe Perches   [CIFS] Neaten cER...
3065
  		cFYI(DBG2, "no very large read support, rsize now 127K");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3066
  	}
d82c2df54   Steve French   [CIFS] minor clea...
3067
3068
3069
  	if (!(tcon->ses->capabilities & CAP_LARGE_READ_X))
  		cifs_sb->rsize = min(cifs_sb->rsize,
  			       (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3070

f7910cbd9   Jeff Layton   cifs: clean up ws...
3071
  	cifs_sb->wsize = cifs_negotiate_wsize(tcon, volume_info);
1bfe73c25   Igor Mammedov   Remote DFS root s...
3072
  remote_path_check:
c1508ca23   Sean Finney   cifs: Add support...
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
  #ifdef CONFIG_CIFS_DFS_UPCALL
  	/*
  	 * Perform an unconditional check for whether there are DFS
  	 * referrals for this path without prefix, to provide support
  	 * for DFS referrals from w2k8 servers which don't seem to respond
  	 * with PATH_NOT_COVERED to requests that include the prefix.
  	 * Chase the referral if found, otherwise continue normally.
  	 */
  	if (referral_walks_count == 0) {
  		int refrc = expand_dfs_referral(xid, pSesInfo, volume_info,
046462abc   Sean Finney   cifs: Simplify ha...
3083
  						cifs_sb, false);
c1508ca23   Sean Finney   cifs: Add support...
3084
3085
3086
3087
3088
3089
  		if (!refrc) {
  			referral_walks_count++;
  			goto try_mount_again;
  		}
  	}
  #endif
f87d39d95   Steve French   [CIFS] Migrate fr...
3090
  	/* check if a whole path is not remote */
709456437   Jeff Layton   cifs: always do i...
3091
  	if (!rc && tcon) {
e4cce94c9   Igor Mammedov   [CIFS] Prevent OO...
3092
  		/* build_path_to_root works only when we have a valid tcon */
f87d39d95   Steve French   [CIFS] Migrate fr...
3093
  		full_path = cifs_build_path_to_root(volume_info, cifs_sb, tcon);
e4cce94c9   Igor Mammedov   [CIFS] Prevent OO...
3094
3095
3096
3097
3098
  		if (full_path == NULL) {
  			rc = -ENOMEM;
  			goto mount_fail_check;
  		}
  		rc = is_path_accessible(xid, tcon, cifs_sb, full_path);
03ceace5c   Jeff Layton   cifs: fix check o...
3099
  		if (rc != 0 && rc != -EREMOTE) {
e4cce94c9   Igor Mammedov   [CIFS] Prevent OO...
3100
3101
3102
3103
3104
  			kfree(full_path);
  			goto mount_fail_check;
  		}
  		kfree(full_path);
  	}
1bfe73c25   Igor Mammedov   Remote DFS root s...
3105
3106
  	/* get referral if needed */
  	if (rc == -EREMOTE) {
d036f50fc   Steve French   [CIFS] Fix build ...
3107
  #ifdef CONFIG_CIFS_DFS_UPCALL
5c2503a8e   Igor Mammedov   Added loop check ...
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
  		if (referral_walks_count > MAX_NESTED_LINKS) {
  			/*
  			 * BB: when we implement proper loop detection,
  			 *     we will remove this check. But now we need it
  			 *     to prevent an indefinite loop if 'DFS tree' is
  			 *     misconfigured (i.e. has loops).
  			 */
  			rc = -ELOOP;
  			goto mount_fail_check;
  		}
1bfe73c25   Igor Mammedov   Remote DFS root s...
3118

dd6139458   Sean Finney   cifs: Extract DFS...
3119
  		rc = expand_dfs_referral(xid, pSesInfo, volume_info, cifs_sb,
046462abc   Sean Finney   cifs: Simplify ha...
3120
  					 true);
7b91e2661   Jeff Layton   cifs: fix error h...
3121

dd6139458   Sean Finney   cifs: Extract DFS...
3122
  		if (!rc) {
5c2503a8e   Igor Mammedov   Added loop check ...
3123
  			referral_walks_count++;
1bfe73c25   Igor Mammedov   Remote DFS root s...
3124
3125
  			goto try_mount_again;
  		}
dd6139458   Sean Finney   cifs: Extract DFS...
3126
  		goto mount_fail_check;
d036f50fc   Steve French   [CIFS] Fix build ...
3127
3128
3129
  #else /* No DFS support, return error on mount */
  		rc = -EOPNOTSUPP;
  #endif
1bfe73c25   Igor Mammedov   Remote DFS root s...
3130
  	}
9d002df49   Jeff Layton   cifs: add routine...
3131
3132
3133
3134
3135
3136
3137
3138
3139
  	if (rc)
  		goto mount_fail_check;
  
  	/* now, hang the tcon off of the superblock */
  	tlink = kzalloc(sizeof *tlink, GFP_KERNEL);
  	if (tlink == NULL) {
  		rc = -ENOMEM;
  		goto mount_fail_check;
  	}
b647c35f7   Jeff Layton   cifs: convert tli...
3140
  	tlink->tl_uid = pSesInfo->linux_uid;
9d002df49   Jeff Layton   cifs: add routine...
3141
3142
3143
3144
  	tlink->tl_tcon = tcon;
  	tlink->tl_time = jiffies;
  	set_bit(TCON_LINK_MASTER, &tlink->tl_flags);
  	set_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
b647c35f7   Jeff Layton   cifs: convert tli...
3145
  	cifs_sb->master_tlink = tlink;
9d002df49   Jeff Layton   cifs: add routine...
3146
  	spin_lock(&cifs_sb->tlink_tree_lock);
b647c35f7   Jeff Layton   cifs: convert tli...
3147
  	tlink_rb_insert(&cifs_sb->tlink_tree, tlink);
9d002df49   Jeff Layton   cifs: add routine...
3148
  	spin_unlock(&cifs_sb->tlink_tree_lock);
413e661c1   Jeff Layton   cifs: store point...
3149

2de970ff6   Jeff Layton   cifs: implement r...
3150
3151
  	queue_delayed_work(system_nrt_wq, &cifs_sb->prune_tlinks,
  				TLINK_IDLE_EXPIRE);
1bfe73c25   Igor Mammedov   Remote DFS root s...
3152
3153
3154
  mount_fail_check:
  	/* on error free sesinfo and tcon struct if needed */
  	if (rc) {
1bfe73c25   Igor Mammedov   Remote DFS root s...
3155
  		/* If find_unc succeeded then rc == 0 so we can not end */
25985edce   Lucas De Marchi   Fix common misspe...
3156
  		/* up accidentally freeing someone elses tcon struct */
1bfe73c25   Igor Mammedov   Remote DFS root s...
3157
3158
3159
3160
3161
3162
  		if (tcon)
  			cifs_put_tcon(tcon);
  		else if (pSesInfo)
  			cifs_put_smb_ses(pSesInfo);
  		else
  			cifs_put_tcp_session(srvTcp);
dd8544661   Al Viro   take bdi setup/de...
3163
  		bdi_destroy(&cifs_sb->bdi);
1bfe73c25   Igor Mammedov   Remote DFS root s...
3164
  	}
70fe7dc05   Jeff Layton   [CIFS] clean up e...
3165
  out:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3166
3167
3168
  	FreeXid(xid);
  	return rc;
  }
8d1bca328   Jeff Layton   cifs: correctly h...
3169
3170
3171
3172
  /*
   * Issue a TREE_CONNECT request. Note that for IPC$ shares, that the tcon
   * pointer may be NULL.
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3173
  int
96daf2b09   Steve French   [CIFS] Rename thr...
3174
3175
  CIFSTCon(unsigned int xid, struct cifs_ses *ses,
  	 const char *tree, struct cifs_tcon *tcon,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3176
3177
3178
3179
3180
3181
3182
3183
  	 const struct nls_table *nls_codepage)
  {
  	struct smb_hdr *smb_buffer;
  	struct smb_hdr *smb_buffer_response;
  	TCONX_REQ *pSMB;
  	TCONX_RSP *pSMBr;
  	unsigned char *bcc_ptr;
  	int rc = 0;
690c522fa   Jeff Layton   cifs: use get/put...
3184
3185
  	int length;
  	__u16 bytes_left, count;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3186
3187
3188
3189
3190
  
  	if (ses == NULL)
  		return -EIO;
  
  	smb_buffer = cifs_buf_get();
ca43e3bee   Steve French   [CIFS] Fix checkp...
3191
  	if (smb_buffer == NULL)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3192
  		return -ENOMEM;
ca43e3bee   Steve French   [CIFS] Fix checkp...
3193

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3194
3195
3196
3197
  	smb_buffer_response = smb_buffer;
  
  	header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX,
  			NULL /*no tid */ , 4 /*wct */ );
1982c344f   Steve French   [CIFS] Ensure tha...
3198
3199
  
  	smb_buffer->Mid = GetNextMid(ses->server);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3200
3201
3202
3203
3204
3205
  	smb_buffer->Uid = ses->Suid;
  	pSMB = (TCONX_REQ *) smb_buffer;
  	pSMBr = (TCONX_RSP *) smb_buffer_response;
  
  	pSMB->AndXCommand = 0xFF;
  	pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3206
  	bcc_ptr = &pSMB->Password[0];
8d1bca328   Jeff Layton   cifs: correctly h...
3207
  	if (!tcon || (ses->server->sec_mode & SECMODE_USER)) {
eeac8047f   Steve French   [CIFS] Fix CIFS t...
3208
  		pSMB->PasswordLength = cpu_to_le16(1);	/* minimum */
7c7b25bc8   Steve French   [CIFS] Support fo...
3209
  		*bcc_ptr = 0; /* password is null byte */
eeac8047f   Steve French   [CIFS] Fix CIFS t...
3210
  		bcc_ptr++;              /* skip password */
7c7b25bc8   Steve French   [CIFS] Support fo...
3211
  		/* already aligned so no need to do it below */
eeac8047f   Steve French   [CIFS] Fix CIFS t...
3212
  	} else {
540b2e377   Shirish Pargaonkar   cifs: Fix regress...
3213
  		pSMB->PasswordLength = cpu_to_le16(CIFS_AUTH_RESP_SIZE);
eeac8047f   Steve French   [CIFS] Fix CIFS t...
3214
3215
3216
  		/* BB FIXME add code to fail this if NTLMv2 or Kerberos
  		   specified as required (when that support is added to
  		   the vfs in the future) as only NTLM or the much
7c7b25bc8   Steve French   [CIFS] Support fo...
3217
  		   weaker LANMAN (which we do not send by default) is accepted
eeac8047f   Steve French   [CIFS] Fix CIFS t...
3218
3219
  		   by Samba (not sure whether other servers allow
  		   NTLMv2 password here) */
7c7b25bc8   Steve French   [CIFS] Support fo...
3220
  #ifdef CONFIG_CIFS_WEAK_PW_HASH
04912d6a2   Jeff Layton   cifs: rename "ext...
3221
  		if ((global_secflags & CIFSSEC_MAY_LANMAN) &&
00e485b01   Jeff Layton   cifs: store passw...
3222
  		    (ses->server->secType == LANMAN))
d3ba50b17   Shirish Pargaonkar   NTLM auth and sig...
3223
  			calc_lanman_hash(tcon->password, ses->server->cryptkey,
96daf2b09   Steve French   [CIFS] Rename thr...
3224
  					 ses->server->sec_mode &
4e53a3fb9   Jeff Layton   cifs: have calc_l...
3225
3226
  					    SECMODE_PW_ENCRYPT ? true : false,
  					 bcc_ptr);
7c7b25bc8   Steve French   [CIFS] Support fo...
3227
3228
  		else
  #endif /* CIFS_WEAK_PW_HASH */
ee2c92585   Shirish Pargaonkar   cifs: More crypto...
3229
3230
  		rc = SMBNTencrypt(tcon->password, ses->server->cryptkey,
  					bcc_ptr);
eeac8047f   Steve French   [CIFS] Fix CIFS t...
3231

540b2e377   Shirish Pargaonkar   cifs: Fix regress...
3232
  		bcc_ptr += CIFS_AUTH_RESP_SIZE;
fb8c4b14d   Steve French   [CIFS] whitespace...
3233
  		if (ses->capabilities & CAP_UNICODE) {
7c7b25bc8   Steve French   [CIFS] Support fo...
3234
3235
3236
3237
  			/* must align unicode strings */
  			*bcc_ptr = 0; /* null byte password */
  			bcc_ptr++;
  		}
eeac8047f   Steve French   [CIFS] Fix CIFS t...
3238
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3239

96daf2b09   Steve French   [CIFS] Rename thr...
3240
  	if (ses->server->sec_mode &
a878fb221   Steve French   [CIFS] Do not lim...
3241
  			(SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
  		smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
  
  	if (ses->capabilities & CAP_STATUS32) {
  		smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
  	}
  	if (ses->capabilities & CAP_DFS) {
  		smb_buffer->Flags2 |= SMBFLG2_DFS;
  	}
  	if (ses->capabilities & CAP_UNICODE) {
  		smb_buffer->Flags2 |= SMBFLG2_UNICODE;
  		length =
50c2f7538   Steve French   [CIFS] whitespace...
3253
3254
  		    cifs_strtoUCS((__le16 *) bcc_ptr, tree,
  			6 /* max utf8 char length in bytes */ *
a878fb221   Steve French   [CIFS] Do not lim...
3255
3256
  			(/* server len*/ + 256 /* share len */), nls_codepage);
  		bcc_ptr += 2 * length;	/* convert num 16 bit words to bytes */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3257
3258
  		bcc_ptr += 2;	/* skip trailing null */
  	} else {		/* ASCII */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3259
3260
3261
3262
3263
3264
3265
  		strcpy(bcc_ptr, tree);
  		bcc_ptr += strlen(tree) + 1;
  	}
  	strcpy(bcc_ptr, "?????");
  	bcc_ptr += strlen("?????");
  	bcc_ptr += 1;
  	count = bcc_ptr - &pSMB->Password[0];
be8e3b004   Steve French   consistently use ...
3266
3267
  	pSMB->hdr.smb_buf_length = cpu_to_be32(be32_to_cpu(
  					pSMB->hdr.smb_buf_length) + count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3268
  	pSMB->ByteCount = cpu_to_le16(count);
133672efb   Steve French   [CIFS] Fix buffer...
3269
  	rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length,
7749981ec   Jeff Layton   cifs: remove code...
3270
  			 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3271

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3272
3273
  	/* above now done in SendReceive */
  	if ((rc == 0) && (tcon != NULL)) {
0e0d2cf32   Steve French   [CIFS] Remove spa...
3274
  		bool is_unicode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3275
  		tcon->tidStatus = CifsGood;
3b7952109   Steve French   [CIFS] Fix cifs r...
3276
  		tcon->need_reconnect = false;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3277
3278
  		tcon->tid = smb_buffer_response->Tid;
  		bcc_ptr = pByteArea(smb_buffer_response);
690c522fa   Jeff Layton   cifs: use get/put...
3279
  		bytes_left = get_bcc(smb_buffer_response);
cc20c031b   Jeff Layton   cifs: convert CIF...
3280
  		length = strnlen(bcc_ptr, bytes_left - 2);
0e0d2cf32   Steve French   [CIFS] Remove spa...
3281
3282
3283
3284
  		if (smb_buffer->Flags2 & SMBFLG2_UNICODE)
  			is_unicode = true;
  		else
  			is_unicode = false;
cc20c031b   Jeff Layton   cifs: convert CIF...
3285

50c2f7538   Steve French   [CIFS] whitespace...
3286
  		/* skip service field (NB: this field is always ASCII) */
7f8ed420f   Steve French   [CIFS] CIFS suppo...
3287
3288
3289
  		if (length == 3) {
  			if ((bcc_ptr[0] == 'I') && (bcc_ptr[1] == 'P') &&
  			    (bcc_ptr[2] == 'C')) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
3290
  				cFYI(1, "IPC connection");
7f8ed420f   Steve French   [CIFS] CIFS suppo...
3291
3292
3293
3294
3295
  				tcon->ipc = 1;
  			}
  		} else if (length == 2) {
  			if ((bcc_ptr[0] == 'A') && (bcc_ptr[1] == ':')) {
  				/* the most common case */
b6b38f704   Joe Perches   [CIFS] Neaten cER...
3296
  				cFYI(1, "disk share connection");
7f8ed420f   Steve French   [CIFS] CIFS suppo...
3297
3298
  			}
  		}
50c2f7538   Steve French   [CIFS] whitespace...
3299
  		bcc_ptr += length + 1;
cc20c031b   Jeff Layton   cifs: convert CIF...
3300
  		bytes_left -= (length + 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3301
  		strncpy(tcon->treeName, tree, MAX_TREE_SIZE);
cc20c031b   Jeff Layton   cifs: convert CIF...
3302
3303
  
  		/* mostly informational -- no need to fail on error here */
90a98b2f3   Jeff Layton   cifs: free native...
3304
  		kfree(tcon->nativeFileSystem);
d185cda77   Steve French   [CIFS] rename cif...
3305
  		tcon->nativeFileSystem = cifs_strndup_from_ucs(bcc_ptr,
0e0d2cf32   Steve French   [CIFS] Remove spa...
3306
  						      bytes_left, is_unicode,
cc20c031b   Jeff Layton   cifs: convert CIF...
3307
  						      nls_codepage);
b6b38f704   Joe Perches   [CIFS] Neaten cER...
3308
  		cFYI(1, "nativeFileSystem=%s", tcon->nativeFileSystem);
cc20c031b   Jeff Layton   cifs: convert CIF...
3309

fb8c4b14d   Steve French   [CIFS] whitespace...
3310
  		if ((smb_buffer_response->WordCount == 3) ||
1a4e15a04   Steve French   [CIFS] Missing fl...
3311
3312
  			 (smb_buffer_response->WordCount == 7))
  			/* field is in same location */
3979877e5   Steve French   [CIFS] Support fo...
3313
3314
3315
  			tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
  		else
  			tcon->Flags = 0;
b6b38f704   Joe Perches   [CIFS] Neaten cER...
3316
  		cFYI(1, "Tcon flags: 0x%x ", tcon->Flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3317
  	} else if ((rc == 0) && tcon == NULL) {
50c2f7538   Steve French   [CIFS] whitespace...
3318
  		/* all we need to save for IPC$ connection */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3319
3320
  		ses->ipc_tid = smb_buffer_response->Tid;
  	}
a8a11d399   Mariusz Kozlowski   [CIFS] remove som...
3321
  	cifs_buf_release(smb_buffer);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3322
3323
  	return rc;
  }
2a9b99516   Al Viro   sanitize cifs_umo...
3324
3325
  void
  cifs_umount(struct cifs_sb_info *cifs_sb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3326
  {
b647c35f7   Jeff Layton   cifs: convert tli...
3327
3328
3329
  	struct rb_root *root = &cifs_sb->tlink_tree;
  	struct rb_node *node;
  	struct tcon_link *tlink;
9d002df49   Jeff Layton   cifs: add routine...
3330

2de970ff6   Jeff Layton   cifs: implement r...
3331
  	cancel_delayed_work_sync(&cifs_sb->prune_tlinks);
b647c35f7   Jeff Layton   cifs: convert tli...
3332
3333
3334
3335
3336
3337
  	spin_lock(&cifs_sb->tlink_tree_lock);
  	while ((node = rb_first(root))) {
  		tlink = rb_entry(node, struct tcon_link, tl_rbnode);
  		cifs_get_tlink(tlink);
  		clear_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
  		rb_erase(node, root);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3338

b647c35f7   Jeff Layton   cifs: convert tli...
3339
3340
3341
3342
3343
  		spin_unlock(&cifs_sb->tlink_tree_lock);
  		cifs_put_tlink(tlink);
  		spin_lock(&cifs_sb->tlink_tree_lock);
  	}
  	spin_unlock(&cifs_sb->tlink_tree_lock);
50c2f7538   Steve French   [CIFS] whitespace...
3344

dd8544661   Al Viro   take bdi setup/de...
3345
  	bdi_destroy(&cifs_sb->bdi);
d757d71bf   Al Viro   cifs: pull freein...
3346
3347
3348
  	kfree(cifs_sb->mountdata);
  	unload_nls(cifs_sb->local_nls);
  	kfree(cifs_sb);
50c2f7538   Steve French   [CIFS] whitespace...
3349
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3350

96daf2b09   Steve French   [CIFS] Rename thr...
3351
  int cifs_negotiate_protocol(unsigned int xid, struct cifs_ses *ses)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3352
3353
  {
  	int rc = 0;
198b56827   Jeff Layton   cifs: break negot...
3354
  	struct TCP_Server_Info *server = ses->server;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3355

198b56827   Jeff Layton   cifs: break negot...
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
  	/* only send once per connect */
  	if (server->maxBuf != 0)
  		return 0;
  
  	rc = CIFSSMBNegotiate(xid, ses);
  	if (rc == -EAGAIN) {
  		/* retry only once on 1st time connection */
  		rc = CIFSSMBNegotiate(xid, ses);
  		if (rc == -EAGAIN)
  			rc = -EHOSTDOWN;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3366
  	}
198b56827   Jeff Layton   cifs: break negot...
3367
3368
  	if (rc == 0) {
  		spin_lock(&GlobalMid_Lock);
7fdbaa1b8   Jeff Layton   cifs: don't allow...
3369
  		if (server->tcpStatus == CifsNeedNegotiate)
198b56827   Jeff Layton   cifs: break negot...
3370
3371
3372
3373
  			server->tcpStatus = CifsGood;
  		else
  			rc = -EHOSTDOWN;
  		spin_unlock(&GlobalMid_Lock);
26b994fad   Steve French   [CIFS] Code clean...
3374

198b56827   Jeff Layton   cifs: break negot...
3375
3376
3377
3378
  	}
  
  	return rc;
  }
96daf2b09   Steve French   [CIFS] Rename thr...
3379
  int cifs_setup_session(unsigned int xid, struct cifs_ses *ses,
198b56827   Jeff Layton   cifs: break negot...
3380
3381
3382
3383
  			struct nls_table *nls_info)
  {
  	int rc = 0;
  	struct TCP_Server_Info *server = ses->server;
26b994fad   Steve French   [CIFS] Code clean...
3384

198b56827   Jeff Layton   cifs: break negot...
3385
3386
  	ses->flags = 0;
  	ses->capabilities = server->capabilities;
26b994fad   Steve French   [CIFS] Code clean...
3387
  	if (linuxExtEnabled == 0)
198b56827   Jeff Layton   cifs: break negot...
3388
  		ses->capabilities &= (~CAP_UNIX);
20418acd6   Steve French   [CIFS] Remove old...
3389

b6b38f704   Joe Perches   [CIFS] Neaten cER...
3390
  	cFYI(1, "Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d",
96daf2b09   Steve French   [CIFS] Rename thr...
3391
  		 server->sec_mode, server->capabilities, server->timeAdj);
cb7691b64   Jeff Layton   cifs: add local s...
3392

198b56827   Jeff Layton   cifs: break negot...
3393
  	rc = CIFS_SessSetup(xid, ses, nls_info);
26b994fad   Steve French   [CIFS] Code clean...
3394
  	if (rc) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
3395
  		cERROR(1, "Send error in SessSetup = %d", rc);
26b994fad   Steve French   [CIFS] Code clean...
3396
  	} else {
5d0d28824   Shirish Pargaonkar   NTLM authenticati...
3397
3398
  		mutex_lock(&ses->server->srv_mutex);
  		if (!server->session_estab) {
21e733930   Shirish Pargaonkar   NTLM auth and sig...
3399
  			server->session_key.response = ses->auth_key.response;
5d0d28824   Shirish Pargaonkar   NTLM authenticati...
3400
  			server->session_key.len = ses->auth_key.len;
21e733930   Shirish Pargaonkar   NTLM auth and sig...
3401
3402
3403
  			server->sequence_number = 0x2;
  			server->session_estab = true;
  			ses->auth_key.response = NULL;
5d0d28824   Shirish Pargaonkar   NTLM authenticati...
3404
3405
  		}
  		mutex_unlock(&server->srv_mutex);
b6b38f704   Joe Perches   [CIFS] Neaten cER...
3406
  		cFYI(1, "CIFS Session Established successfully");
20418acd6   Steve French   [CIFS] Remove old...
3407
  		spin_lock(&GlobalMid_Lock);
198b56827   Jeff Layton   cifs: break negot...
3408
3409
  		ses->status = CifsGood;
  		ses->need_reconnect = false;
20418acd6   Steve French   [CIFS] Remove old...
3410
  		spin_unlock(&GlobalMid_Lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3411
  	}
26b994fad   Steve French   [CIFS] Code clean...
3412

21e733930   Shirish Pargaonkar   NTLM auth and sig...
3413
3414
3415
  	kfree(ses->auth_key.response);
  	ses->auth_key.response = NULL;
  	ses->auth_key.len = 0;
d3686d54c   Shirish Pargaonkar   cifs: Cleanup and...
3416
3417
  	kfree(ses->ntlmssp);
  	ses->ntlmssp = NULL;
21e733930   Shirish Pargaonkar   NTLM auth and sig...
3418

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3419
3420
  	return rc;
  }
96daf2b09   Steve French   [CIFS] Rename thr...
3421
  static struct cifs_tcon *
9d002df49   Jeff Layton   cifs: add routine...
3422
3423
  cifs_construct_tcon(struct cifs_sb_info *cifs_sb, uid_t fsuid)
  {
96daf2b09   Steve French   [CIFS] Rename thr...
3424
3425
3426
  	struct cifs_tcon *master_tcon = cifs_sb_master_tcon(cifs_sb);
  	struct cifs_ses *ses;
  	struct cifs_tcon *tcon = NULL;
9d002df49   Jeff Layton   cifs: add routine...
3427
  	struct smb_vol *vol_info;
34c87901e   Steve French   Shrink stack spac...
3428
3429
3430
  	char username[28]; /* big enough for "krb50x" + hex of ULONG_MAX 6+16 */
  			   /* We used to have this as MAX_USERNAME which is   */
  			   /* way too big now (256 instead of 32) */
9d002df49   Jeff Layton   cifs: add routine...
3431
3432
3433
3434
3435
3436
  
  	vol_info = kzalloc(sizeof(*vol_info), GFP_KERNEL);
  	if (vol_info == NULL) {
  		tcon = ERR_PTR(-ENOMEM);
  		goto out;
  	}
ea1be1a3c   Steve French   [CIFS] update lim...
3437
  	snprintf(username, sizeof(username), "krb50x%x", fsuid);
9d002df49   Jeff Layton   cifs: add routine...
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
  	vol_info->username = username;
  	vol_info->local_nls = cifs_sb->local_nls;
  	vol_info->linux_uid = fsuid;
  	vol_info->cred_uid = fsuid;
  	vol_info->UNC = master_tcon->treeName;
  	vol_info->retry = master_tcon->retry;
  	vol_info->nocase = master_tcon->nocase;
  	vol_info->local_lease = master_tcon->local_lease;
  	vol_info->no_linux_ext = !master_tcon->unix_ext;
  
  	/* FIXME: allow for other secFlg settings */
  	vol_info->secFlg = CIFSSEC_MUST_KRB5;
  
  	/* get a reference for the same TCP session */
3f9bcca78   Suresh Jayaraman   cifs: convert cif...
3452
  	spin_lock(&cifs_tcp_ses_lock);
9d002df49   Jeff Layton   cifs: add routine...
3453
  	++master_tcon->ses->server->srv_count;
3f9bcca78   Suresh Jayaraman   cifs: convert cif...
3454
  	spin_unlock(&cifs_tcp_ses_lock);
9d002df49   Jeff Layton   cifs: add routine...
3455
3456
3457
  
  	ses = cifs_get_smb_ses(master_tcon->ses->server, vol_info);
  	if (IS_ERR(ses)) {
96daf2b09   Steve French   [CIFS] Rename thr...
3458
  		tcon = (struct cifs_tcon *)ses;
9d002df49   Jeff Layton   cifs: add routine...
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
  		cifs_put_tcp_session(master_tcon->ses->server);
  		goto out;
  	}
  
  	tcon = cifs_get_tcon(ses, vol_info);
  	if (IS_ERR(tcon)) {
  		cifs_put_smb_ses(ses);
  		goto out;
  	}
  
  	if (ses->capabilities & CAP_UNIX)
  		reset_cifs_unix_caps(0, tcon, NULL, vol_info);
  out:
  	kfree(vol_info);
  
  	return tcon;
  }
96daf2b09   Steve French   [CIFS] Rename thr...
3476
  struct cifs_tcon *
9d002df49   Jeff Layton   cifs: add routine...
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
  cifs_sb_master_tcon(struct cifs_sb_info *cifs_sb)
  {
  	return tlink_tcon(cifs_sb_master_tlink(cifs_sb));
  }
  
  static int
  cifs_sb_tcon_pending_wait(void *unused)
  {
  	schedule();
  	return signal_pending(current) ? -ERESTARTSYS : 0;
  }
b647c35f7   Jeff Layton   cifs: convert tli...
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
  /* find and return a tlink with given uid */
  static struct tcon_link *
  tlink_rb_search(struct rb_root *root, uid_t uid)
  {
  	struct rb_node *node = root->rb_node;
  	struct tcon_link *tlink;
  
  	while (node) {
  		tlink = rb_entry(node, struct tcon_link, tl_rbnode);
  
  		if (tlink->tl_uid > uid)
  			node = node->rb_left;
  		else if (tlink->tl_uid < uid)
  			node = node->rb_right;
  		else
  			return tlink;
  	}
  	return NULL;
  }
  
  /* insert a tcon_link into the tree */
  static void
  tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink)
  {
  	struct rb_node **new = &(root->rb_node), *parent = NULL;
  	struct tcon_link *tlink;
  
  	while (*new) {
  		tlink = rb_entry(*new, struct tcon_link, tl_rbnode);
  		parent = *new;
  
  		if (tlink->tl_uid > new_tlink->tl_uid)
  			new = &((*new)->rb_left);
  		else
  			new = &((*new)->rb_right);
  	}
  
  	rb_link_node(&new_tlink->tl_rbnode, parent, new);
  	rb_insert_color(&new_tlink->tl_rbnode, root);
  }
9d002df49   Jeff Layton   cifs: add routine...
3528
3529
3530
3531
3532
3533
3534
  /*
   * Find or construct an appropriate tcon given a cifs_sb and the fsuid of the
   * current task.
   *
   * If the superblock doesn't refer to a multiuser mount, then just return
   * the master tcon for the mount.
   *
6ef933a38   Suresh Jayaraman   cifs: trivial com...
3535
   * First, search the rbtree for an existing tcon for this fsuid. If one
9d002df49   Jeff Layton   cifs: add routine...
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
   * exists, then check to see if it's pending construction. If it is then wait
   * for construction to complete. Once it's no longer pending, check to see if
   * it failed and either return an error or retry construction, depending on
   * the timeout.
   *
   * If one doesn't exist then insert a new tcon_link struct into the tree and
   * try to construct a new one.
   */
  struct tcon_link *
  cifs_sb_tlink(struct cifs_sb_info *cifs_sb)
  {
  	int ret;
b647c35f7   Jeff Layton   cifs: convert tli...
3548
  	uid_t fsuid = current_fsuid();
9d002df49   Jeff Layton   cifs: add routine...
3549
3550
3551
3552
3553
3554
  	struct tcon_link *tlink, *newtlink;
  
  	if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER))
  		return cifs_get_tlink(cifs_sb_master_tlink(cifs_sb));
  
  	spin_lock(&cifs_sb->tlink_tree_lock);
b647c35f7   Jeff Layton   cifs: convert tli...
3555
  	tlink = tlink_rb_search(&cifs_sb->tlink_tree, fsuid);
9d002df49   Jeff Layton   cifs: add routine...
3556
3557
3558
3559
3560
3561
3562
3563
  	if (tlink)
  		cifs_get_tlink(tlink);
  	spin_unlock(&cifs_sb->tlink_tree_lock);
  
  	if (tlink == NULL) {
  		newtlink = kzalloc(sizeof(*tlink), GFP_KERNEL);
  		if (newtlink == NULL)
  			return ERR_PTR(-ENOMEM);
b647c35f7   Jeff Layton   cifs: convert tli...
3564
  		newtlink->tl_uid = fsuid;
9d002df49   Jeff Layton   cifs: add routine...
3565
3566
3567
3568
  		newtlink->tl_tcon = ERR_PTR(-EACCES);
  		set_bit(TCON_LINK_PENDING, &newtlink->tl_flags);
  		set_bit(TCON_LINK_IN_TREE, &newtlink->tl_flags);
  		cifs_get_tlink(newtlink);
9d002df49   Jeff Layton   cifs: add routine...
3569
3570
  		spin_lock(&cifs_sb->tlink_tree_lock);
  		/* was one inserted after previous search? */
b647c35f7   Jeff Layton   cifs: convert tli...
3571
  		tlink = tlink_rb_search(&cifs_sb->tlink_tree, fsuid);
9d002df49   Jeff Layton   cifs: add routine...
3572
3573
3574
  		if (tlink) {
  			cifs_get_tlink(tlink);
  			spin_unlock(&cifs_sb->tlink_tree_lock);
9d002df49   Jeff Layton   cifs: add routine...
3575
3576
3577
  			kfree(newtlink);
  			goto wait_for_construction;
  		}
9d002df49   Jeff Layton   cifs: add routine...
3578
  		tlink = newtlink;
b647c35f7   Jeff Layton   cifs: convert tli...
3579
3580
  		tlink_rb_insert(&cifs_sb->tlink_tree, tlink);
  		spin_unlock(&cifs_sb->tlink_tree_lock);
9d002df49   Jeff Layton   cifs: add routine...
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
  	} else {
  wait_for_construction:
  		ret = wait_on_bit(&tlink->tl_flags, TCON_LINK_PENDING,
  				  cifs_sb_tcon_pending_wait,
  				  TASK_INTERRUPTIBLE);
  		if (ret) {
  			cifs_put_tlink(tlink);
  			return ERR_PTR(ret);
  		}
  
  		/* if it's good, return it */
  		if (!IS_ERR(tlink->tl_tcon))
  			return tlink;
  
  		/* return error if we tried this already recently */
  		if (time_before(jiffies, tlink->tl_time + TLINK_ERROR_EXPIRE)) {
  			cifs_put_tlink(tlink);
  			return ERR_PTR(-EACCES);
  		}
  
  		if (test_and_set_bit(TCON_LINK_PENDING, &tlink->tl_flags))
  			goto wait_for_construction;
  	}
  
  	tlink->tl_tcon = cifs_construct_tcon(cifs_sb, fsuid);
  	clear_bit(TCON_LINK_PENDING, &tlink->tl_flags);
  	wake_up_bit(&tlink->tl_flags, TCON_LINK_PENDING);
  
  	if (IS_ERR(tlink->tl_tcon)) {
  		cifs_put_tlink(tlink);
  		return ERR_PTR(-EACCES);
  	}
  
  	return tlink;
  }
2de970ff6   Jeff Layton   cifs: implement r...
3616
3617
3618
3619
3620
3621
3622
3623
3624
3625
  
  /*
   * periodic workqueue job that scans tcon_tree for a superblock and closes
   * out tcons.
   */
  static void
  cifs_prune_tlinks(struct work_struct *work)
  {
  	struct cifs_sb_info *cifs_sb = container_of(work, struct cifs_sb_info,
  						    prune_tlinks.work);
b647c35f7   Jeff Layton   cifs: convert tli...
3626
3627
3628
3629
  	struct rb_root *root = &cifs_sb->tlink_tree;
  	struct rb_node *node = rb_first(root);
  	struct rb_node *tmp;
  	struct tcon_link *tlink;
2de970ff6   Jeff Layton   cifs: implement r...
3630

b647c35f7   Jeff Layton   cifs: convert tli...
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
3647
3648
  	/*
  	 * Because we drop the spinlock in the loop in order to put the tlink
  	 * it's not guarded against removal of links from the tree. The only
  	 * places that remove entries from the tree are this function and
  	 * umounts. Because this function is non-reentrant and is canceled
  	 * before umount can proceed, this is safe.
  	 */
  	spin_lock(&cifs_sb->tlink_tree_lock);
  	node = rb_first(root);
  	while (node != NULL) {
  		tmp = node;
  		node = rb_next(tmp);
  		tlink = rb_entry(tmp, struct tcon_link, tl_rbnode);
  
  		if (test_bit(TCON_LINK_MASTER, &tlink->tl_flags) ||
  		    atomic_read(&tlink->tl_count) != 0 ||
  		    time_after(tlink->tl_time + TLINK_IDLE_EXPIRE, jiffies))
  			continue;
2de970ff6   Jeff Layton   cifs: implement r...
3649

b647c35f7   Jeff Layton   cifs: convert tli...
3650
3651
3652
3653
3654
3655
3656
3657
3658
  		cifs_get_tlink(tlink);
  		clear_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
  		rb_erase(tmp, root);
  
  		spin_unlock(&cifs_sb->tlink_tree_lock);
  		cifs_put_tlink(tlink);
  		spin_lock(&cifs_sb->tlink_tree_lock);
  	}
  	spin_unlock(&cifs_sb->tlink_tree_lock);
2de970ff6   Jeff Layton   cifs: implement r...
3659
3660
3661
3662
  
  	queue_delayed_work(system_nrt_wq, &cifs_sb->prune_tlinks,
  				TLINK_IDLE_EXPIRE);
  }