Blame view

fs/cifs/connect.c 108 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>
143cb494c   Paul Gortmaker   fs: add module.h ...
40
  #include <linux/module.h>
0e2bedaa3   Steve French   [CIFS] ipv6_addr_...
41
  #include <net/ipv6.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
42
43
44
45
46
47
48
49
50
  #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...
51
  #include "fscache.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
52
53
54
  
  #define CIFS_PORT 445
  #define RFC1001_PORT 139
c74093b69   Jeff Layton   cifs: set up recu...
55
56
  /* SMB echo "timeout" -- FIXME: tunable? */
  #define SMB_ECHO_INTERVAL (60 * HZ)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
57
  extern mempool_t *cifs_req_poolp;
2de970ff6   Jeff Layton   cifs: implement r...
58
  /* FIXME: should these be tunable? */
9d002df49   Jeff Layton   cifs: add routine...
59
  #define TLINK_ERROR_EXPIRE	(1 * HZ)
2de970ff6   Jeff Layton   cifs: implement r...
60
  #define TLINK_IDLE_EXPIRE	(600 * HZ)
9d002df49   Jeff Layton   cifs: add routine...
61

a9f1b85e5   Pavel Shilovsky   CIFS: Simplify ip...
62
63
  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...
64
  static void tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink);
2de970ff6   Jeff Layton   cifs: implement r...
65
  static void cifs_prune_tlinks(struct work_struct *work);
b9bce2e9f   Jeff Layton   cifs: fix expand_...
66
67
  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
68

d5c5605c2   Jeff Layton   cifs: make ipv6_c...
69
70
71
72
73
74
75
76
  /*
   * 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...
77
  static int
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
78
79
80
  cifs_reconnect(struct TCP_Server_Info *server)
  {
  	int rc = 0;
f1987b44f   Jeff Layton   cifs: reinstate s...
81
  	struct list_head *tmp, *tmp2;
96daf2b09   Steve French   [CIFS] Rename thr...
82
83
  	struct cifs_ses *ses;
  	struct cifs_tcon *tcon;
fb8c4b14d   Steve French   [CIFS] whitespace...
84
  	struct mid_q_entry *mid_entry;
3c1105df6   Jeff Layton   cifs: don't call ...
85
  	struct list_head retry_list;
50c2f7538   Steve French   [CIFS] whitespace...
86

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
87
  	spin_lock(&GlobalMid_Lock);
469ee614a   Jeff Layton   [CIFS] eliminate ...
88
  	if (server->tcpStatus == CifsExiting) {
fb8c4b14d   Steve French   [CIFS] whitespace...
89
  		/* the demux thread will exit normally
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
90
91
92
93
94
95
96
  		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...
97
  	cFYI(1, "Reconnecting tcp session");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
98
99
100
  
  	/* 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...
101
  	cFYI(1, "%s: marking sessions and tcons for reconnect", __func__);
3f9bcca78   Suresh Jayaraman   cifs: convert cif...
102
  	spin_lock(&cifs_tcp_ses_lock);
14fbf50d6   Jeff Layton   cifs: reinstate s...
103
  	list_for_each(tmp, &server->smb_ses_list) {
96daf2b09   Steve French   [CIFS] Rename thr...
104
  		ses = list_entry(tmp, struct cifs_ses, smb_ses_list);
14fbf50d6   Jeff Layton   cifs: reinstate s...
105
106
  		ses->need_reconnect = true;
  		ses->ipc_tid = 0;
f1987b44f   Jeff Layton   cifs: reinstate s...
107
  		list_for_each(tmp2, &ses->tcon_list) {
96daf2b09   Steve French   [CIFS] Rename thr...
108
  			tcon = list_entry(tmp2, struct cifs_tcon, tcon_list);
3b7952109   Steve French   [CIFS] Fix cifs r...
109
  			tcon->need_reconnect = true;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
110
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
111
  	}
3f9bcca78   Suresh Jayaraman   cifs: convert cif...
112
  	spin_unlock(&cifs_tcp_ses_lock);
2b84a36c5   Jeff Layton   cifs: allow for d...
113

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

2b84a36c5   Jeff Layton   cifs: allow for d...
135
  	/* mark submitted MIDs for retry and issue callback */
3c1105df6   Jeff Layton   cifs: don't call ...
136
137
  	INIT_LIST_HEAD(&retry_list);
  	cFYI(1, "%s: moving mids to private list", __func__);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
138
  	spin_lock(&GlobalMid_Lock);
2b84a36c5   Jeff Layton   cifs: allow for d...
139
140
141
  	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...
142
  			mid_entry->midState = MID_RETRY_NEEDED;
3c1105df6   Jeff Layton   cifs: don't call ...
143
144
145
146
147
148
149
  		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...
150
151
  		list_del_init(&mid_entry->qhead);
  		mid_entry->callback(mid_entry);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
152
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
153

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

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

fb8c4b14d   Steve French   [CIFS] whitespace...
186
  	if (pSMB->Command != SMB_COM_TRANSACTION2)
e4eb295d3   Steve French   [PATCH] cifs: Han...
187
  		return 0;
fb8c4b14d   Steve French   [CIFS] whitespace...
188
189
190
  	/* 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...
191
  		cFYI(1, "invalid transact2 word count");
e4eb295d3   Steve French   [PATCH] cifs: Han...
192
193
194
195
  		return -EINVAL;
  	}
  
  	pSMBt = (struct smb_t2_rsp *)pSMB;
26ec25486   Jeff Layton   cifs: fix unalign...
196
197
  	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...
198

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

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

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

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

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

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

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

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

2a2047bc9   Jeff Layton   cifs: sanitize le...
280
  	memcpy(data_area_of_target, data_area_of_buf2, total_in_buf2);
fb8c4b14d   Steve French   [CIFS] whitespace...
281
  	if (remaining == total_in_buf2) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
282
  		cFYI(1, "found the last secondary response");
e4eb295d3   Steve French   [PATCH] cifs: Han...
283
284
285
  		return 0; /* we are done */
  	} else /* more responses to go */
  		return 1;
e4eb295d3   Steve French   [PATCH] cifs: Han...
286
  }
c74093b69   Jeff Layton   cifs: set up recu...
287
288
289
290
291
292
  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 ...
293
  	/*
195291e68   Jeff Layton   cifs: clean up ch...
294
295
296
  	 * 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 ...
297
  	 */
195291e68   Jeff Layton   cifs: clean up ch...
298
  	if (server->maxBuf == 0 ||
247ec9b41   Jeff Layton   cifs: don't send ...
299
  	    time_before(jiffies, server->lstrp + SMB_ECHO_INTERVAL - HZ))
c74093b69   Jeff Layton   cifs: set up recu...
300
301
302
303
304
305
306
307
308
309
  		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...
310
  static bool
2a37ef94b   Jeff Layton   cifs: move buffer...
311
  allocate_buffers(struct TCP_Server_Info *server)
3d9c2472a   Pavel Shilovsky   CIFS: Move buffer...
312
  {
2a37ef94b   Jeff Layton   cifs: move buffer...
313
314
315
  	if (!server->bigbuf) {
  		server->bigbuf = (char *)cifs_buf_get();
  		if (!server->bigbuf) {
3d9c2472a   Pavel Shilovsky   CIFS: Move buffer...
316
317
318
319
320
  			cERROR(1, "No memory for large SMB response");
  			msleep(3000);
  			/* retry will check if exiting */
  			return false;
  		}
2a37ef94b   Jeff Layton   cifs: move buffer...
321
  	} else if (server->large_buf) {
3d9c2472a   Pavel Shilovsky   CIFS: Move buffer...
322
  		/* we are reusing a dirty large buf, clear its start */
2a37ef94b   Jeff Layton   cifs: move buffer...
323
  		memset(server->bigbuf, 0, sizeof(struct smb_hdr));
3d9c2472a   Pavel Shilovsky   CIFS: Move buffer...
324
  	}
2a37ef94b   Jeff Layton   cifs: move buffer...
325
326
327
  	if (!server->smallbuf) {
  		server->smallbuf = (char *)cifs_small_buf_get();
  		if (!server->smallbuf) {
3d9c2472a   Pavel Shilovsky   CIFS: Move buffer...
328
329
330
331
332
333
334
335
  			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 */
2a37ef94b   Jeff Layton   cifs: move buffer...
336
  		memset(server->smallbuf, 0, sizeof(struct smb_hdr));
3d9c2472a   Pavel Shilovsky   CIFS: Move buffer...
337
  	}
3d9c2472a   Pavel Shilovsky   CIFS: Move buffer...
338
339
  	return true;
  }
ba749e6d5   Jeff Layton   cifs: check for u...
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
  static bool
  server_unresponsive(struct TCP_Server_Info *server)
  {
  	if (echo_retries > 0 && server->tcpStatus == CifsGood &&
  	    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);
  		wake_up(&server->response_q);
  		return true;
  	}
  
  	return false;
  }
42c4dfc21   Jeff Layton   cifs: turn read_f...
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
  /*
   * kvec_array_init - clone a kvec array, and advance into it
   * @new:	pointer to memory for cloned array
   * @iov:	pointer to original array
   * @nr_segs:	number of members in original array
   * @bytes:	number of bytes to advance into the cloned array
   *
   * This function will copy the array provided in iov to a section of memory
   * and advance the specified number of bytes into the new array. It returns
   * the number of segments in the new array. "new" must be at least as big as
   * the original iov array.
   */
  static unsigned int
  kvec_array_init(struct kvec *new, struct kvec *iov, unsigned int nr_segs,
  		size_t bytes)
  {
  	size_t base = 0;
  
  	while (bytes || !iov->iov_len) {
  		int copy = min(bytes, iov->iov_len);
  
  		bytes -= copy;
  		base += copy;
  		if (iov->iov_len == base) {
  			iov++;
  			nr_segs--;
  			base = 0;
  		}
  	}
  	memcpy(new, iov, sizeof(*iov) * nr_segs);
  	new->iov_base += base;
  	new->iov_len -= base;
  	return nr_segs;
  }
1041e3f99   Jeff Layton   cifs: keep a reus...
390
391
  static struct kvec *
  get_server_iovec(struct TCP_Server_Info *server, unsigned int nr_segs)
e7015fb1c   Pavel Shilovsky   CIFS: Simplify so...
392
  {
1041e3f99   Jeff Layton   cifs: keep a reus...
393
394
395
396
397
398
399
400
401
402
403
404
405
406
  	struct kvec *new_iov;
  
  	if (server->iov && nr_segs <= server->nr_iov)
  		return server->iov;
  
  	/* not big enough -- allocate a new one and release the old */
  	new_iov = kmalloc(sizeof(*new_iov) * nr_segs, GFP_NOFS);
  	if (new_iov) {
  		kfree(server->iov);
  		server->iov = new_iov;
  		server->nr_iov = nr_segs;
  	}
  	return new_iov;
  }
e28bc5b1f   Jeff Layton   cifs: add cifs_as...
407
408
409
  int
  cifs_readv_from_socket(struct TCP_Server_Info *server, struct kvec *iov_orig,
  		       unsigned int nr_segs, unsigned int to_read)
e7015fb1c   Pavel Shilovsky   CIFS: Simplify so...
410
  {
a52c1eb7a   Jeff Layton   cifs: simplify re...
411
412
  	int length = 0;
  	int total_read;
42c4dfc21   Jeff Layton   cifs: turn read_f...
413
  	unsigned int segs;
e831e6cf3   Jeff Layton   cifs: make smb_ms...
414
  	struct msghdr smb_msg;
42c4dfc21   Jeff Layton   cifs: turn read_f...
415
  	struct kvec *iov;
1041e3f99   Jeff Layton   cifs: keep a reus...
416
  	iov = get_server_iovec(server, nr_segs);
42c4dfc21   Jeff Layton   cifs: turn read_f...
417
418
  	if (!iov)
  		return -ENOMEM;
e7015fb1c   Pavel Shilovsky   CIFS: Simplify so...
419

e831e6cf3   Jeff Layton   cifs: make smb_ms...
420
421
  	smb_msg.msg_control = NULL;
  	smb_msg.msg_controllen = 0;
a52c1eb7a   Jeff Layton   cifs: simplify re...
422
  	for (total_read = 0; to_read; total_read += length, to_read -= length) {
95edcff49   Jeff Layton   cifs: attempt to ...
423
  		try_to_freeze();
ba749e6d5   Jeff Layton   cifs: check for u...
424
  		if (server_unresponsive(server)) {
a52c1eb7a   Jeff Layton   cifs: simplify re...
425
  			total_read = -EAGAIN;
ba749e6d5   Jeff Layton   cifs: check for u...
426
427
  			break;
  		}
42c4dfc21   Jeff Layton   cifs: turn read_f...
428
429
430
431
  		segs = kvec_array_init(iov, iov_orig, nr_segs, total_read);
  
  		length = kernel_recvmsg(server->ssocket, &smb_msg,
  					iov, segs, to_read, 0);
e7015fb1c   Pavel Shilovsky   CIFS: Simplify so...
432

e7015fb1c   Pavel Shilovsky   CIFS: Simplify so...
433
  		if (server->tcpStatus == CifsExiting) {
a52c1eb7a   Jeff Layton   cifs: simplify re...
434
  			total_read = -ESHUTDOWN;
e7015fb1c   Pavel Shilovsky   CIFS: Simplify so...
435
436
437
  			break;
  		} else if (server->tcpStatus == CifsNeedReconnect) {
  			cifs_reconnect(server);
a52c1eb7a   Jeff Layton   cifs: simplify re...
438
  			total_read = -EAGAIN;
e7015fb1c   Pavel Shilovsky   CIFS: Simplify so...
439
440
441
442
443
444
445
446
447
448
449
  			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;
a52c1eb7a   Jeff Layton   cifs: simplify re...
450
  			continue;
e7015fb1c   Pavel Shilovsky   CIFS: Simplify so...
451
  		} else if (length <= 0) {
a52c1eb7a   Jeff Layton   cifs: simplify re...
452
453
  			cFYI(1, "Received no data or error: expecting %d "
  				"got %d", to_read, length);
e7015fb1c   Pavel Shilovsky   CIFS: Simplify so...
454
  			cifs_reconnect(server);
a52c1eb7a   Jeff Layton   cifs: simplify re...
455
  			total_read = -EAGAIN;
e7015fb1c   Pavel Shilovsky   CIFS: Simplify so...
456
457
458
  			break;
  		}
  	}
a52c1eb7a   Jeff Layton   cifs: simplify re...
459
  	return total_read;
e7015fb1c   Pavel Shilovsky   CIFS: Simplify so...
460
  }
e7015fb1c   Pavel Shilovsky   CIFS: Simplify so...
461

e28bc5b1f   Jeff Layton   cifs: add cifs_as...
462
463
464
  int
  cifs_read_from_socket(struct TCP_Server_Info *server, char *buf,
  		      unsigned int to_read)
42c4dfc21   Jeff Layton   cifs: turn read_f...
465
466
467
468
469
  {
  	struct kvec iov;
  
  	iov.iov_base = buf;
  	iov.iov_len = to_read;
e28bc5b1f   Jeff Layton   cifs: add cifs_as...
470
  	return cifs_readv_from_socket(server, &iov, 1, to_read);
e7015fb1c   Pavel Shilovsky   CIFS: Simplify so...
471
  }
98bac62c9   Pavel Shilovsky   CIFS: Move RFC100...
472
  static bool
fe11e4ccb   Jeff Layton   cifs: clean up ch...
473
  is_smb_response(struct TCP_Server_Info *server, unsigned char type)
98bac62c9   Pavel Shilovsky   CIFS: Move RFC100...
474
  {
98bac62c9   Pavel Shilovsky   CIFS: Move RFC100...
475
476
477
478
479
  	/*
  	 * 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.
  	 */
fe11e4ccb   Jeff Layton   cifs: clean up ch...
480
481
482
483
484
485
486
487
488
489
490
  	switch (type) {
  	case RFC1002_SESSION_MESSAGE:
  		/* Regular SMB response */
  		return true;
  	case RFC1002_SESSION_KEEP_ALIVE:
  		cFYI(1, "RFC 1002 session keep alive");
  		break;
  	case RFC1002_POSITIVE_SESSION_RESPONSE:
  		cFYI(1, "RFC 1002 positive session response");
  		break;
  	case RFC1002_NEGATIVE_SESSION_RESPONSE:
98bac62c9   Pavel Shilovsky   CIFS: Move RFC100...
491
492
493
494
  		/*
  		 * We get this from Windows 98 instead of an error on
  		 * SMB negprot response.
  		 */
fe11e4ccb   Jeff Layton   cifs: clean up ch...
495
  		cFYI(1, "RFC 1002 negative session response");
98bac62c9   Pavel Shilovsky   CIFS: Move RFC100...
496
497
498
499
500
501
502
503
  		/* 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).
  		 */
fe11e4ccb   Jeff Layton   cifs: clean up ch...
504
  		cifs_set_port((struct sockaddr *)&server->dstaddr, CIFS_PORT);
98bac62c9   Pavel Shilovsky   CIFS: Move RFC100...
505
506
  		cifs_reconnect(server);
  		wake_up(&server->response_q);
fe11e4ccb   Jeff Layton   cifs: clean up ch...
507
508
509
  		break;
  	default:
  		cERROR(1, "RFC 1002 unknown response type 0x%x", type);
98bac62c9   Pavel Shilovsky   CIFS: Move RFC100...
510
  		cifs_reconnect(server);
98bac62c9   Pavel Shilovsky   CIFS: Move RFC100...
511
  	}
fe11e4ccb   Jeff Layton   cifs: clean up ch...
512
  	return false;
98bac62c9   Pavel Shilovsky   CIFS: Move RFC100...
513
  }
ad69bae17   Pavel Shilovsky   CIFS: Move mid se...
514
  static struct mid_q_entry *
ea1f4502f   Jeff Layton   cifs: move mid fi...
515
  find_mid(struct TCP_Server_Info *server, struct smb_hdr *buf)
ad69bae17   Pavel Shilovsky   CIFS: Move mid se...
516
  {
ea1f4502f   Jeff Layton   cifs: move mid fi...
517
  	struct mid_q_entry *mid;
ad69bae17   Pavel Shilovsky   CIFS: Move mid se...
518
519
  
  	spin_lock(&GlobalMid_Lock);
ea1f4502f   Jeff Layton   cifs: move mid fi...
520
521
522
523
524
525
  	list_for_each_entry(mid, &server->pending_mid_q, qhead) {
  		if (mid->mid == buf->Mid &&
  		    mid->midState == MID_REQUEST_SUBMITTED &&
  		    mid->command == buf->Command) {
  			spin_unlock(&GlobalMid_Lock);
  			return mid;
ad69bae17   Pavel Shilovsky   CIFS: Move mid se...
526
  		}
ea1f4502f   Jeff Layton   cifs: move mid fi...
527
528
529
530
  	}
  	spin_unlock(&GlobalMid_Lock);
  	return NULL;
  }
e28bc5b1f   Jeff Layton   cifs: add cifs_as...
531
532
  void
  dequeue_mid(struct mid_q_entry *mid, bool malformed)
ea1f4502f   Jeff Layton   cifs: move mid fi...
533
  {
ad69bae17   Pavel Shilovsky   CIFS: Move mid se...
534
  #ifdef CONFIG_CIFS_STATS2
ea1f4502f   Jeff Layton   cifs: move mid fi...
535
  	mid->when_received = jiffies;
ad69bae17   Pavel Shilovsky   CIFS: Move mid se...
536
  #endif
ea1f4502f   Jeff Layton   cifs: move mid fi...
537
538
539
540
541
542
  	spin_lock(&GlobalMid_Lock);
  	if (!malformed)
  		mid->midState = MID_RESPONSE_RECEIVED;
  	else
  		mid->midState = MID_RESPONSE_MALFORMED;
  	list_del_init(&mid->qhead);
ad69bae17   Pavel Shilovsky   CIFS: Move mid se...
543
  	spin_unlock(&GlobalMid_Lock);
ea1f4502f   Jeff Layton   cifs: move mid fi...
544
  }
ad69bae17   Pavel Shilovsky   CIFS: Move mid se...
545

c8054ebdb   Jeff Layton   cifs: find mid ea...
546
547
548
  static void
  handle_mid(struct mid_q_entry *mid, struct TCP_Server_Info *server,
  	   struct smb_hdr *buf, int malformed)
ea1f4502f   Jeff Layton   cifs: move mid fi...
549
  {
ffc00e27a   Jeff Layton   cifs: eliminate i...
550
551
  	if (malformed == 0 && check2ndT2(buf) > 0) {
  		mid->multiRsp = true;
ea1f4502f   Jeff Layton   cifs: move mid fi...
552
553
  		if (mid->resp_buf) {
  			/* merge response - fix up 1st*/
ffc00e27a   Jeff Layton   cifs: eliminate i...
554
555
  			malformed = coalesce_t2(buf, mid->resp_buf);
  			if (malformed > 0)
c8054ebdb   Jeff Layton   cifs: find mid ea...
556
  				return;
ffc00e27a   Jeff Layton   cifs: eliminate i...
557

ea1f4502f   Jeff Layton   cifs: move mid fi...
558
559
  			/* All parts received or packet is malformed. */
  			mid->multiEnd = true;
c8054ebdb   Jeff Layton   cifs: find mid ea...
560
  			return dequeue_mid(mid, malformed);
ea1f4502f   Jeff Layton   cifs: move mid fi...
561
  		}
2a37ef94b   Jeff Layton   cifs: move buffer...
562
  		if (!server->large_buf) {
ea1f4502f   Jeff Layton   cifs: move mid fi...
563
564
565
566
567
568
  			/*FIXME: switch to already allocated largebuf?*/
  			cERROR(1, "1st trans2 resp needs bigbuf");
  		} else {
  			/* Have first buffer */
  			mid->resp_buf = buf;
  			mid->largeBuf = true;
2a37ef94b   Jeff Layton   cifs: move buffer...
569
  			server->bigbuf = NULL;
ea1f4502f   Jeff Layton   cifs: move mid fi...
570
  		}
c8054ebdb   Jeff Layton   cifs: find mid ea...
571
  		return;
ea1f4502f   Jeff Layton   cifs: move mid fi...
572
573
  	}
  	mid->resp_buf = buf;
2a37ef94b   Jeff Layton   cifs: move buffer...
574
575
576
577
578
579
580
581
582
  	mid->largeBuf = server->large_buf;
  	/* Was previous buf put in mpx struct for multi-rsp? */
  	if (!mid->multiRsp) {
  		/* smb buffer will be freed by user thread */
  		if (server->large_buf)
  			server->bigbuf = NULL;
  		else
  			server->smallbuf = NULL;
  	}
ffc00e27a   Jeff Layton   cifs: eliminate i...
583
  	dequeue_mid(mid, malformed);
ad69bae17   Pavel Shilovsky   CIFS: Move mid se...
584
  }
762dfd105   Pavel Shilovsky   CIFS: Cleanup dem...
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
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
  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);
1041e3f99   Jeff Layton   cifs: keep a reus...
672
  	kfree(server->iov);
762dfd105   Pavel Shilovsky   CIFS: Cleanup dem...
673
674
675
676
677
678
679
  	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...
680
  static int
e9097ab48   Jeff Layton   cifs: break out 3...
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
  standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid)
  {
  	int length;
  	char *buf = server->smallbuf;
  	struct smb_hdr *smb_buffer = (struct smb_hdr *)buf;
  	unsigned int pdu_length = be32_to_cpu(smb_buffer->smb_buf_length);
  
  	/* make sure this will fit in a large buffer */
  	if (pdu_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
  		cERROR(1, "SMB response too long (%u bytes)",
  			pdu_length);
  		cifs_reconnect(server);
  		wake_up(&server->response_q);
  		return -EAGAIN;
  	}
  
  	/* switch to large buffer if too big for a small one */
  	if (pdu_length > MAX_CIFS_SMALL_BUFFER_SIZE - 4) {
  		server->large_buf = true;
  		memcpy(server->bigbuf, server->smallbuf, server->total_read);
  		buf = server->bigbuf;
  		smb_buffer = (struct smb_hdr *)buf;
  	}
  
  	/* now read the rest */
e28bc5b1f   Jeff Layton   cifs: add cifs_as...
706
  	length = cifs_read_from_socket(server,
e9097ab48   Jeff Layton   cifs: break out 3...
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
  			  buf + sizeof(struct smb_hdr) - 1,
  			  pdu_length - sizeof(struct smb_hdr) + 1 + 4);
  	if (length < 0)
  		return length;
  	server->total_read += length;
  
  	dump_smb(smb_buffer, server->total_read);
  
  	/*
  	 * 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, server->total_read);
  	if (length != 0)
  		cifs_dump_mem("Bad SMB: ", buf,
  			min_t(unsigned int, server->total_read, 48));
  
  	if (mid)
  		handle_mid(mid, server, smb_buffer, length);
  
  	return length;
  }
  
  static int
7c97c200e   Al Viro   cifs: fix the typ...
736
  cifs_demultiplex_thread(void *p)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
737
738
  {
  	int length;
7c97c200e   Al Viro   cifs: fix the typ...
739
  	struct TCP_Server_Info *server = p;
2a37ef94b   Jeff Layton   cifs: move buffer...
740
741
  	unsigned int pdu_length;
  	char *buf = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
742
  	struct smb_hdr *smb_buffer = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
743
744
  	struct task_struct *task_to_wake = NULL;
  	struct mid_q_entry *mid_entry;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
745

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
746
  	current->flags |= PF_MEMALLOC;
b6b38f704   Joe Perches   [CIFS] Neaten cER...
747
  	cFYI(1, "Demultiplex PID: %d", task_pid_nr(current));
93d0ec851   Jeff Layton   remove locking ar...
748
749
750
  
  	length = atomic_inc_return(&tcpSesAllocCount);
  	if (length > 1)
26f57364d   Steve French   [CIFS] formatting...
751
752
  		mempool_resize(cifs_req_poolp, length + cifs_min_rcv,
  				GFP_KERNEL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
753

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

2a37ef94b   Jeff Layton   cifs: move buffer...
759
  		if (!allocate_buffers(server))
3d9c2472a   Pavel Shilovsky   CIFS: Move buffer...
760
  			continue;
b8643e1b5   Steve French   [PATCH] cifs: Do ...
761

2a37ef94b   Jeff Layton   cifs: move buffer...
762
763
764
  		server->large_buf = false;
  		smb_buffer = (struct smb_hdr *)server->smallbuf;
  		buf = server->smallbuf;
f01d5e14e   Steve French   [CIFS] fix for in...
765
  		pdu_length = 4; /* enough to get RFC1001 header */
fda359436   Steve French   [CIFS] cifs: reco...
766

e28bc5b1f   Jeff Layton   cifs: add cifs_as...
767
  		length = cifs_read_from_socket(server, buf, pdu_length);
a52c1eb7a   Jeff Layton   cifs: simplify re...
768
  		if (length < 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
769
  			continue;
2a37ef94b   Jeff Layton   cifs: move buffer...
770
  		server->total_read = length;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
771

98bac62c9   Pavel Shilovsky   CIFS: Move RFC100...
772
773
774
775
  		/*
  		 * The right amount was read from socket - 4 bytes,
  		 * so we can now interpret the length field.
  		 */
be8e3b004   Steve French   consistently use ...
776
  		pdu_length = be32_to_cpu(smb_buffer->smb_buf_length);
70ca734a1   Steve French   [CIFS] Various mi...
777

fe11e4ccb   Jeff Layton   cifs: clean up ch...
778
779
  		cFYI(1, "RFC1002 header 0x%x", pdu_length);
  		if (!is_smb_response(server, buf[0]))
fb8c4b14d   Steve French   [CIFS] whitespace...
780
  			continue;
e4eb295d3   Steve French   [PATCH] cifs: Han...
781

89482a56a   Jeff Layton   cifs: add a third...
782
783
784
785
786
787
788
  		/* make sure we have enough to get to the MID */
  		if (pdu_length < sizeof(struct smb_hdr) - 1 - 4) {
  			cERROR(1, "SMB response too short (%u bytes)",
  				pdu_length);
  			cifs_reconnect(server);
  			wake_up(&server->response_q);
  			continue;
e4eb295d3   Steve French   [PATCH] cifs: Han...
789
  		}
e7015fb1c   Pavel Shilovsky   CIFS: Simplify so...
790

89482a56a   Jeff Layton   cifs: add a third...
791
  		/* read down to the MID */
e28bc5b1f   Jeff Layton   cifs: add cifs_as...
792
793
  		length = cifs_read_from_socket(server, buf + 4,
  					sizeof(struct smb_hdr) - 1 - 4);
89482a56a   Jeff Layton   cifs: add a third...
794
  		if (length < 0)
e4eb295d3   Steve French   [PATCH] cifs: Han...
795
  			continue;
2a37ef94b   Jeff Layton   cifs: move buffer...
796
  		server->total_read += length;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
797

c8054ebdb   Jeff Layton   cifs: find mid ea...
798
  		mid_entry = find_mid(server, smb_buffer);
50c2f7538   Steve French   [CIFS] whitespace...
799

44d22d846   Jeff Layton   cifs: add a callb...
800
801
802
803
  		if (!mid_entry || !mid_entry->receive)
  			length = standard_receive3(server, mid_entry);
  		else
  			length = mid_entry->receive(server, mid_entry);
71823baff   Jeff Layton   cifs: don't alway...
804

e9097ab48   Jeff Layton   cifs: break out 3...
805
  		if (length < 0)
fe11e4ccb   Jeff Layton   cifs: clean up ch...
806
  			continue;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
807

e9097ab48   Jeff Layton   cifs: break out 3...
808
  		if (server->large_buf) {
2a37ef94b   Jeff Layton   cifs: move buffer...
809
  			buf = server->bigbuf;
e9097ab48   Jeff Layton   cifs: break out 3...
810
  			smb_buffer = (struct smb_hdr *)buf;
e4eb295d3   Steve French   [PATCH] cifs: Han...
811
  		}
fda359436   Steve French   [CIFS] cifs: reco...
812

fda359436   Steve French   [CIFS] cifs: reco...
813
  		server->lstrp = jiffies;
2b84a36c5   Jeff Layton   cifs: allow for d...
814
  		if (mid_entry != NULL) {
2a37ef94b   Jeff Layton   cifs: move buffer...
815
816
  			if (!mid_entry->multiRsp || mid_entry->multiEnd)
  				mid_entry->callback(mid_entry);
ffc00e27a   Jeff Layton   cifs: eliminate i...
817
  		} else if (!is_valid_oplock_break(smb_buffer, server)) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
818
  			cERROR(1, "No task to wake, unknown frame received! "
8097531a5   Jeff Layton   cifs: clean up ac...
819
  				   "NumMids %d", atomic_read(&midCount));
3d9c2472a   Pavel Shilovsky   CIFS: Move buffer...
820
  			cifs_dump_mem("Received Data is: ", buf,
70ca734a1   Steve French   [CIFS] Various mi...
821
  				      sizeof(struct smb_hdr));
3979877e5   Steve French   [CIFS] Support fo...
822
823
824
825
  #ifdef CONFIG_CIFS_DEBUG2
  			cifs_dump_detail(smb_buffer);
  			cifs_dump_mids(server);
  #endif /* CIFS_DEBUG2 */
50c2f7538   Steve French   [CIFS] whitespace...
826

e4eb295d3   Steve French   [PATCH] cifs: Han...
827
828
  		}
  	} /* end while !EXITING */
fd62cb7e7   Justin P. Mattock   fs:cifs:connect.c...
829
  	/* buffer usually freed in free_mid - need to free it here on exit */
2a37ef94b   Jeff Layton   cifs: move buffer...
830
831
832
  	cifs_buf_release(server->bigbuf);
  	if (server->smallbuf) /* no sense logging a debug message if NULL */
  		cifs_small_buf_release(server->smallbuf);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
833

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

b1c8d2b42   Jeff Layton   cifs: handle the ...
837
838
839
840
841
842
843
844
845
  	/* 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...
846
  	module_put_and_exit(0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
847
  }
c359cf3c6   Jeff Layton   [CIFS] add hostna...
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
  /* 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
875
  static int
b946845a9   Sean Finney   cifs: cifs_parse_...
876
  cifs_parse_mount_options(const char *mountdata, const char *devname,
50c2f7538   Steve French   [CIFS] whitespace...
877
  			 struct smb_vol *vol)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
878
  {
4906e50b3   Pavel Shilovsky   CIFS: Fix memory ...
879
  	char *value, *data, *end;
957df4535   Vasily Averin   possible memory c...
880
  	char *mountdata_copy = NULL, *options;
3d3ea8e64   Shirish Pargaonkar   cifs: Add mount o...
881
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
882
883
  	unsigned int  temp_len, i, j;
  	char separator[2];
9b9d6b243   Jeff Layton   cifs: reinstate o...
884
885
886
887
  	short int override_uid = -1;
  	short int override_gid = -1;
  	bool uid_specified = false;
  	bool gid_specified = false;
884639996   Jeff Layton   cifs: remove Loca...
888
  	char *nodename = utsname()->nodename;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
889
890
  
  	separator[0] = ',';
50c2f7538   Steve French   [CIFS] whitespace...
891
  	separator[1] = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
892

884639996   Jeff Layton   cifs: remove Loca...
893
894
895
896
897
  	/*
  	 * 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...
898
899
  	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...
900
  		vol->source_rfc1001_name[i] = toupper(nodename[i]);
1397f2ee4   Jeff Layton   cifs: replace som...
901
  	vol->source_rfc1001_name[RFC1001_NAME_LEN] = 0;
a10faeb2a   Steve French   [CIFS] Support fo...
902
903
904
  	/* 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...
905
906
  	vol->cred_uid = current_uid();
  	vol->linux_uid = current_uid();
a001e5b55   David Howells   CRED: Wrap task c...
907
  	vol->linux_gid = current_gid();
f55ed1a83   Jeff Layton   cifs: tighten up ...
908
909
910
  
  	/* 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
911
912
  
  	/* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
ac67055ef   Jeremy Allison   [CIFS] POSIX exte...
913
914
  	/* default is always to request posix paths. */
  	vol->posix_paths = 1;
a0c9217f6   Jeff Layton   cifs: make server...
915
916
  	/* default to using server inode numbers where available */
  	vol->server_ino = 1;
ac67055ef   Jeremy Allison   [CIFS] POSIX exte...
917

6d20e8406   Suresh Jayaraman   cifs: add attribu...
918
  	vol->actimeo = CIFS_DEF_ACTIMEO;
b946845a9   Sean Finney   cifs: cifs_parse_...
919
920
921
922
923
924
  	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
925

b946845a9   Sean Finney   cifs: cifs_parse_...
926
  	options = mountdata_copy;
4906e50b3   Pavel Shilovsky   CIFS: Fix memory ...
927
  	end = options + strlen(options);
50c2f7538   Steve French   [CIFS] whitespace...
928
  	if (strncmp(options, "sep=", 4) == 0) {
fb8c4b14d   Steve French   [CIFS] whitespace...
929
  		if (options[4] != 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
930
931
932
  			separator[0] = options[4];
  			options += 5;
  		} else {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
933
  			cFYI(1, "Null separator not allowed");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
934
935
  		}
  	}
3d3ea8e64   Shirish Pargaonkar   cifs: Add mount o...
936
937
  	vol->backupuid_specified = false; /* no backup intent for a user */
  	vol->backupgid_specified = false; /* no backup intent for a group */
50c2f7538   Steve French   [CIFS] whitespace...
938

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
939
940
941
942
943
  	while ((data = strsep(&options, separator)) != NULL) {
  		if (!*data)
  			continue;
  		if ((value = strchr(data, '=')) != NULL)
  			*value++ = '\0';
50c2f7538   Steve French   [CIFS] whitespace...
944
945
  		/* Have to parse this before we parse for "user" */
  		if (strnicmp(data, "user_xattr", 10) == 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
946
  			vol->no_xattr = 0;
50c2f7538   Steve French   [CIFS] whitespace...
947
  		} else if (strnicmp(data, "nouser_xattr", 12) == 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
948
949
  			vol->no_xattr = 1;
  		} else if (strnicmp(data, "user", 4) == 0) {
4b952a9b0   Steve French   [CIFS] Allow null...
950
  			if (!value) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
951
952
953
  				printk(KERN_WARNING
  				       "CIFS: invalid or missing username
  ");
b946845a9   Sean Finney   cifs: cifs_parse_...
954
  				goto cifs_parse_mount_err;
fb8c4b14d   Steve French   [CIFS] whitespace...
955
  			} else if (!*value) {
4b952a9b0   Steve French   [CIFS] Allow null...
956
957
  				/* null user, ie anonymous, authentication */
  				vol->nullauth = 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
958
  			}
8727c8a85   Steve French   Allow user names ...
959
960
  			if (strnlen(value, MAX_USERNAME_SIZE) <
  						MAX_USERNAME_SIZE) {
b946845a9   Sean Finney   cifs: cifs_parse_...
961
962
963
964
965
966
967
  				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
968
969
970
  			} else {
  				printk(KERN_WARNING "CIFS: username too long
  ");
b946845a9   Sean Finney   cifs: cifs_parse_...
971
  				goto cifs_parse_mount_err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
972
973
974
975
976
  			}
  		} else if (strnicmp(data, "pass", 4) == 0) {
  			if (!value) {
  				vol->password = NULL;
  				continue;
fb8c4b14d   Steve French   [CIFS] whitespace...
977
  			} else if (value[0] == 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
978
979
980
981
  				/* 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...
982
  				if (value[1] != separator[0]) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
983
984
985
986
987
988
989
  					vol->password = NULL;
  					continue;
  				}
  			}
  			temp_len = strlen(value);
  			/* removed password length check, NTLM passwords
  				can be arbitrarily long */
50c2f7538   Steve French   [CIFS] whitespace...
990
  			/* if comma in password, the string will be
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
991
992
993
994
995
996
997
998
  			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...
999
  			if ((value[temp_len] == 0) &&
4906e50b3   Pavel Shilovsky   CIFS: Fix memory ...
1000
  			    (value + temp_len < end) &&
09d1db5c6   Steve French   [PATCH] cifs: imp...
1001
  			    (value[temp_len+1] == separator[0])) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1002
1003
  				/* reinsert comma */
  				value[temp_len] = separator[0];
50c2f7538   Steve French   [CIFS] whitespace...
1004
1005
  				temp_len += 2;  /* move after second comma */
  				while (value[temp_len] != 0)  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1006
  					if (value[temp_len] == separator[0]) {
50c2f7538   Steve French   [CIFS] whitespace...
1007
  						if (value[temp_len+1] ==
09d1db5c6   Steve French   [PATCH] cifs: imp...
1008
1009
1010
  						     separator[0]) {
  						/* skip second comma */
  							temp_len++;
50c2f7538   Steve French   [CIFS] whitespace...
1011
  						} else {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1012
1013
1014
1015
1016
1017
1018
  						/* single comma indicating start
  							 of next parm */
  							break;
  						}
  					}
  					temp_len++;
  				}
fb8c4b14d   Steve French   [CIFS] whitespace...
1019
  				if (value[temp_len] == 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1020
1021
1022
1023
1024
1025
  					options = NULL;
  				} else {
  					value[temp_len] = 0;
  					/* point option to start of next parm */
  					options = value + temp_len + 1;
  				}
50c2f7538   Steve French   [CIFS] whitespace...
1026
  				/* go from value to value + temp_len condensing
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1027
1028
  				double commas to singles. Note that this ends up
  				allocating a few bytes too many, which is ok */
e915fc497   Pekka Enberg   [PATCH] fs: conve...
1029
  				vol->password = kzalloc(temp_len, GFP_KERNEL);
fb8c4b14d   Steve French   [CIFS] whitespace...
1030
  				if (vol->password == NULL) {
50c2f7538   Steve French   [CIFS] whitespace...
1031
1032
1033
  					printk(KERN_WARNING "CIFS: no memory "
  							    "for password
  ");
b946845a9   Sean Finney   cifs: cifs_parse_...
1034
  					goto cifs_parse_mount_err;
433dc24f2   Steve French   [PATCH] cifs: rem...
1035
  				}
50c2f7538   Steve French   [CIFS] whitespace...
1036
  				for (i = 0, j = 0; i < temp_len; i++, j++) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1037
  					vol->password[j] = value[i];
fb8c4b14d   Steve French   [CIFS] whitespace...
1038
  					if (value[i] == separator[0]
09d1db5c6   Steve French   [PATCH] cifs: imp...
1039
  						&& value[i+1] == separator[0]) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1040
1041
1042
1043
1044
1045
  						/* skip second comma */
  						i++;
  					}
  				}
  				vol->password[j] = 0;
  			} else {
e915fc497   Pekka Enberg   [PATCH] fs: conve...
1046
  				vol->password = kzalloc(temp_len+1, GFP_KERNEL);
fb8c4b14d   Steve French   [CIFS] whitespace...
1047
  				if (vol->password == NULL) {
50c2f7538   Steve French   [CIFS] whitespace...
1048
1049
1050
  					printk(KERN_WARNING "CIFS: no memory "
  							    "for password
  ");
b946845a9   Sean Finney   cifs: cifs_parse_...
1051
  					goto cifs_parse_mount_err;
433dc24f2   Steve French   [PATCH] cifs: rem...
1052
  				}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1053
1054
  				strcpy(vol->password, value);
  			}
58f7f68f2   Jeff Layton   cifs: add addr= m...
1055
1056
  		} else if (!strnicmp(data, "ip", 2) ||
  			   !strnicmp(data, "addr", 4)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1057
1058
  			if (!value || !*value) {
  				vol->UNCip = NULL;
50b64e3b7   Jeff Layton   cifs: fix IPv6 ad...
1059
1060
  			} else if (strnlen(value, INET6_ADDRSTRLEN) <
  							INET6_ADDRSTRLEN) {
b946845a9   Sean Finney   cifs: cifs_parse_...
1061
1062
1063
1064
1065
1066
1067
  				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
1068
  			} else {
50c2f7538   Steve French   [CIFS] whitespace...
1069
1070
1071
  				printk(KERN_WARNING "CIFS: ip address "
  						    "too long
  ");
b946845a9   Sean Finney   cifs: cifs_parse_...
1072
  				goto cifs_parse_mount_err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1073
  			}
50c2f7538   Steve French   [CIFS] whitespace...
1074
1075
  		} else if (strnicmp(data, "sec", 3) == 0) {
  			if (!value || !*value) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
1076
  				cERROR(1, "no security value specified");
50c2f7538   Steve French   [CIFS] whitespace...
1077
1078
1079
  				continue;
  			} else if (strnicmp(value, "krb5i", 5) == 0) {
  				vol->secFlg |= CIFSSEC_MAY_KRB5 |
189acaaef   Steve French   [CIFS] Enable sec...
1080
  					CIFSSEC_MUST_SIGN;
bf8206791   Steve French   [CIFS] Kerberos a...
1081
  			} else if (strnicmp(value, "krb5p", 5) == 0) {
50c2f7538   Steve French   [CIFS] whitespace...
1082
1083
  				/* vol->secFlg |= CIFSSEC_MUST_SEAL |
  					CIFSSEC_MAY_KRB5; */
b6b38f704   Joe Perches   [CIFS] Neaten cER...
1084
  				cERROR(1, "Krb5 cifs privacy not supported");
b946845a9   Sean Finney   cifs: cifs_parse_...
1085
  				goto cifs_parse_mount_err;
bf8206791   Steve French   [CIFS] Kerberos a...
1086
  			} else if (strnicmp(value, "krb5", 4) == 0) {
750d1151a   Steve French   [CIFS] Fix alloca...
1087
  				vol->secFlg |= CIFSSEC_MAY_KRB5;
ac6839246   Steve French   [CIFS] Allow raw ...
1088
1089
1090
1091
1092
  			} 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...
1093
  			} else if (strnicmp(value, "ntlmv2i", 7) == 0) {
750d1151a   Steve French   [CIFS] Fix alloca...
1094
  				vol->secFlg |= CIFSSEC_MAY_NTLMV2 |
189acaaef   Steve French   [CIFS] Enable sec...
1095
  					CIFSSEC_MUST_SIGN;
bf8206791   Steve French   [CIFS] Kerberos a...
1096
  			} else if (strnicmp(value, "ntlmv2", 6) == 0) {
750d1151a   Steve French   [CIFS] Fix alloca...
1097
  				vol->secFlg |= CIFSSEC_MAY_NTLMV2;
bf8206791   Steve French   [CIFS] Kerberos a...
1098
  			} else if (strnicmp(value, "ntlmi", 5) == 0) {
750d1151a   Steve French   [CIFS] Fix alloca...
1099
  				vol->secFlg |= CIFSSEC_MAY_NTLM |
189acaaef   Steve French   [CIFS] Enable sec...
1100
  					CIFSSEC_MUST_SIGN;
bf8206791   Steve French   [CIFS] Kerberos a...
1101
1102
  			} else if (strnicmp(value, "ntlm", 4) == 0) {
  				/* ntlm is default so can be turned off too */
750d1151a   Steve French   [CIFS] Fix alloca...
1103
  				vol->secFlg |= CIFSSEC_MAY_NTLM;
bf8206791   Steve French   [CIFS] Kerberos a...
1104
  			} else if (strnicmp(value, "nontlm", 6) == 0) {
189acaaef   Steve French   [CIFS] Enable sec...
1105
  				/* BB is there a better way to do this? */
750d1151a   Steve French   [CIFS] Fix alloca...
1106
  				vol->secFlg |= CIFSSEC_MAY_NTLMV2;
189acaaef   Steve French   [CIFS] Enable sec...
1107
1108
  #ifdef CONFIG_CIFS_WEAK_PW_HASH
  			} else if (strnicmp(value, "lanman", 6) == 0) {
50c2f7538   Steve French   [CIFS] whitespace...
1109
  				vol->secFlg |= CIFSSEC_MAY_LANMAN;
189acaaef   Steve French   [CIFS] Enable sec...
1110
  #endif
bf8206791   Steve French   [CIFS] Kerberos a...
1111
  			} else if (strnicmp(value, "none", 4) == 0) {
189acaaef   Steve French   [CIFS] Enable sec...
1112
  				vol->nullauth = 1;
50c2f7538   Steve French   [CIFS] whitespace...
1113
  			} else {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
1114
  				cERROR(1, "bad security option: %s", value);
b946845a9   Sean Finney   cifs: cifs_parse_...
1115
  				goto cifs_parse_mount_err;
50c2f7538   Steve French   [CIFS] whitespace...
1116
  			}
1cb06d0b5   Steve French   Introduce smb2 mo...
1117
1118
1119
1120
1121
1122
1123
1124
  		} 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...
1125
  			}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1126
1127
1128
1129
  		} 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...
1130
1131
1132
  				printk(KERN_WARNING "CIFS: invalid path to "
  						    "network resource
  ");
b946845a9   Sean Finney   cifs: cifs_parse_...
1133
  				goto cifs_parse_mount_err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1134
1135
  			}
  			if ((temp_len = strnlen(value, 300)) < 300) {
50c2f7538   Steve French   [CIFS] whitespace...
1136
  				vol->UNC = kmalloc(temp_len+1, GFP_KERNEL);
4523cc304   Steve French   [CIFS] UID/GID ov...
1137
  				if (vol->UNC == NULL)
b946845a9   Sean Finney   cifs: cifs_parse_...
1138
  					goto cifs_parse_mount_err;
50c2f7538   Steve French   [CIFS] whitespace...
1139
  				strcpy(vol->UNC, value);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1140
1141
1142
  				if (strncmp(vol->UNC, "//", 2) == 0) {
  					vol->UNC[0] = '\\';
  					vol->UNC[1] = '\\';
50c2f7538   Steve French   [CIFS] whitespace...
1143
  				} else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1144
  					printk(KERN_WARNING
50c2f7538   Steve French   [CIFS] whitespace...
1145
1146
1147
  					       "CIFS: UNC Path does not begin "
  					       "with // or \\\\ 
  ");
b946845a9   Sean Finney   cifs: cifs_parse_...
1148
  					goto cifs_parse_mount_err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1149
1150
1151
1152
  				}
  			} else {
  				printk(KERN_WARNING "CIFS: UNC name too long
  ");
b946845a9   Sean Finney   cifs: cifs_parse_...
1153
  				goto cifs_parse_mount_err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1154
1155
1156
1157
1158
1159
  			}
  		} 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_...
1160
  				goto cifs_parse_mount_err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1161
1162
1163
  			}
  			/* 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...
1164
  			if (strnlen(value, 256) < 256) {
b946845a9   Sean Finney   cifs: cifs_parse_...
1165
1166
1167
1168
1169
1170
1171
  				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...
1172
  				cFYI(1, "Domain name set");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1173
  			} else {
50c2f7538   Steve French   [CIFS] whitespace...
1174
1175
1176
  				printk(KERN_WARNING "CIFS: domain name too "
  						    "long
  ");
b946845a9   Sean Finney   cifs: cifs_parse_...
1177
  				goto cifs_parse_mount_err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1178
  			}
3eb9a8893   Ben Greear   cifs: Allow bindi...
1179
1180
1181
1182
1183
1184
1185
  		} 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_...
1186
  				goto cifs_parse_mount_err;
3eb9a8893   Ben Greear   cifs: Allow bindi...
1187
1188
1189
  			}
  			i = cifs_convert_address((struct sockaddr *)&vol->srcaddr,
  						 value, strlen(value));
b235f371a   Dan Carpenter   cifs: cifs_conver...
1190
  			if (i == 0) {
3eb9a8893   Ben Greear   cifs: Allow bindi...
1191
1192
1193
1194
  				printk(KERN_WARNING "CIFS:  Could not parse"
  				       " srcaddr: %s
  ",
  				       value);
b946845a9   Sean Finney   cifs: cifs_parse_...
1195
  				goto cifs_parse_mount_err;
3eb9a8893   Ben Greear   cifs: Allow bindi...
1196
  			}
50c2f7538   Steve French   [CIFS] whitespace...
1197
1198
1199
1200
1201
  		} else if (strnicmp(data, "prefixpath", 10) == 0) {
  			if (!value || !*value) {
  				printk(KERN_WARNING
  					"CIFS: invalid path prefix
  ");
b946845a9   Sean Finney   cifs: cifs_parse_...
1202
  				goto cifs_parse_mount_err;
50c2f7538   Steve French   [CIFS] whitespace...
1203
1204
  			}
  			if ((temp_len = strnlen(value, 1024)) < 1024) {
4523cc304   Steve French   [CIFS] UID/GID ov...
1205
  				if (value[0] != '/')
2fe87f02a   Steve French   [CIFS] Support de...
1206
  					temp_len++;  /* missing leading slash */
50c2f7538   Steve French   [CIFS] whitespace...
1207
1208
  				vol->prepath = kmalloc(temp_len+1, GFP_KERNEL);
  				if (vol->prepath == NULL)
b946845a9   Sean Finney   cifs: cifs_parse_...
1209
  					goto cifs_parse_mount_err;
4523cc304   Steve French   [CIFS] UID/GID ov...
1210
  				if (value[0] != '/') {
2fe87f02a   Steve French   [CIFS] Support de...
1211
  					vol->prepath[0] = '/';
50c2f7538   Steve French   [CIFS] whitespace...
1212
  					strcpy(vol->prepath+1, value);
2fe87f02a   Steve French   [CIFS] Support de...
1213
  				} else
50c2f7538   Steve French   [CIFS] whitespace...
1214
  					strcpy(vol->prepath, value);
b6b38f704   Joe Perches   [CIFS] Neaten cER...
1215
  				cFYI(1, "prefix path %s", vol->prepath);
50c2f7538   Steve French   [CIFS] whitespace...
1216
1217
1218
  			} else {
  				printk(KERN_WARNING "CIFS: prefix too long
  ");
b946845a9   Sean Finney   cifs: cifs_parse_...
1219
  				goto cifs_parse_mount_err;
50c2f7538   Steve French   [CIFS] whitespace...
1220
  			}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1221
1222
  		} else if (strnicmp(data, "iocharset", 9) == 0) {
  			if (!value || !*value) {
63135e088   Steve French   [CIFS] More white...
1223
1224
1225
  				printk(KERN_WARNING "CIFS: invalid iocharset "
  						    "specified
  ");
b946845a9   Sean Finney   cifs: cifs_parse_...
1226
  				goto cifs_parse_mount_err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1227
1228
  			}
  			if (strnlen(value, 65) < 65) {
b946845a9   Sean Finney   cifs: cifs_parse_...
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
  				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...
1241
1242
  				/* if iocharset not set then load_nls_default
  				   is used by caller */
b6b38f704   Joe Perches   [CIFS] Neaten cER...
1243
  				cFYI(1, "iocharset set to %s", value);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1244
  			} else {
63135e088   Steve French   [CIFS] More white...
1245
1246
1247
  				printk(KERN_WARNING "CIFS: iocharset name "
  						    "too long.
  ");
b946845a9   Sean Finney   cifs: cifs_parse_...
1248
  				goto cifs_parse_mount_err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1249
  			}
9b9d6b243   Jeff Layton   cifs: reinstate o...
1250
1251
1252
  		} 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= ...
1253
1254
  		} else if (!strnicmp(data, "cruid", 5) && value && *value) {
  			vol->cred_uid = simple_strtoul(value, &value, 0);
9b9d6b243   Jeff Layton   cifs: reinstate o...
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
  		} 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
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
  		} 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...
1297
  			if (!value || !*value) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
1298
  				cERROR(1, "no socket option specified");
6a5fa2362   Steve French   [CIFS] Add suppor...
1299
1300
1301
  				continue;
  			} else if (strnicmp(value, "TCP_NODELAY", 11) == 0) {
  				vol->sockopt_tcp_nodelay = 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1302
1303
1304
  			}
  		} else if (strnicmp(data, "netbiosname", 4) == 0) {
  			if (!value || !*value || (*value == ' ')) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
1305
  				cFYI(1, "invalid (empty) netbiosname");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1306
  			} else {
1397f2ee4   Jeff Layton   cifs: replace som...
1307
1308
1309
1310
1311
1312
1313
1314
1315
  				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...
1316
  					if (value[i] == 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1317
  						break;
1397f2ee4   Jeff Layton   cifs: replace som...
1318
  					vol->source_rfc1001_name[i] = value[i];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1319
1320
1321
  				}
  				/* The string has 16th byte zero still from
  				set at top of the function  */
1397f2ee4   Jeff Layton   cifs: replace som...
1322
  				if (i == RFC1001_NAME_LEN && value[i] != 0)
50c2f7538   Steve French   [CIFS] whitespace...
1323
1324
1325
  					printk(KERN_WARNING "CIFS: netbiosname"
  						" longer than 15 truncated.
  ");
a10faeb2a   Steve French   [CIFS] Support fo...
1326
1327
1328
1329
  			}
  		} else if (strnicmp(data, "servern", 7) == 0) {
  			/* servernetbiosname specified override *SMBSERVER */
  			if (!value || !*value || (*value == ' ')) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
1330
  				cFYI(1, "empty server netbiosname specified");
a10faeb2a   Steve French   [CIFS] Support fo...
1331
1332
  			} else {
  				/* last byte, type, is 0x20 for servr type */
1397f2ee4   Jeff Layton   cifs: replace som...
1333
1334
  				memset(vol->target_rfc1001_name, 0x20,
  					RFC1001_NAME_LEN_WITH_NULL);
a10faeb2a   Steve French   [CIFS] Support fo...
1335

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

50c2f7538   Steve French   [CIFS] whitespace...
1341
1342
1343
  				/* user or mount helper must uppercase
  				   the netbiosname */
  					if (value[i] == 0)
a10faeb2a   Steve French   [CIFS] Support fo...
1344
1345
  						break;
  					else
50c2f7538   Steve French   [CIFS] whitespace...
1346
1347
  						vol->target_rfc1001_name[i] =
  								value[i];
a10faeb2a   Steve French   [CIFS] Support fo...
1348
1349
1350
  				}
  				/* The string has 16th byte zero still from
  				   set at top of the function  */
1397f2ee4   Jeff Layton   cifs: replace som...
1351
  				if (i == RFC1001_NAME_LEN && value[i] != 0)
50c2f7538   Steve French   [CIFS] whitespace...
1352
1353
1354
  					printk(KERN_WARNING "CIFS: server net"
  					"biosname longer than 15 truncated.
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1355
  			}
6d20e8406   Suresh Jayaraman   cifs: add attribu...
1356
1357
1358
1359
1360
1361
1362
  		} 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_...
1363
  					goto cifs_parse_mount_err;
6d20e8406   Suresh Jayaraman   cifs: add attribu...
1364
1365
  				}
  			}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1366
1367
1368
1369
  		} else if (strnicmp(data, "credentials", 4) == 0) {
  			/* ignore */
  		} else if (strnicmp(data, "version", 3) == 0) {
  			/* ignore */
50c2f7538   Steve French   [CIFS] whitespace...
1370
  		} else if (strnicmp(data, "guest", 5) == 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1371
  			/* ignore */
c9c7fa006   Steve French   Fix the conflict ...
1372
  		} else if (strnicmp(data, "rw", 2) == 0 && strlen(data) == 2) {
71a394faa   Steve French   [CIFS] remove unk...
1373
1374
1375
  			/* ignore */
  		} else if (strnicmp(data, "ro", 2) == 0) {
  			/* ignore */
edf1ae403   Steve French   [CIFS] Reduce num...
1376
1377
1378
1379
  		} 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
1380
1381
1382
1383
1384
1385
1386
1387
  		} 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...
1388
1389
1390
1391
1392
  			    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
1393
  			continue;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1394
1395
1396
1397
1398
1399
1400
1401
  		} 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...
1402
1403
1404
1405
  		} 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...
1406
1407
1408
1409
  		} 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 ...
1410
1411
  		} else if (strnicmp(data, "nodfs", 5) == 0) {
  			vol->nodfs = 1;
ac67055ef   Jeremy Allison   [CIFS] POSIX exte...
1412
1413
1414
1415
  		} 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...
1416
1417
1418
1419
  		} 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...
1420
  		} else if ((strnicmp(data, "nocase", 6) == 0) ||
a10faeb2a   Steve French   [CIFS] Support fo...
1421
  			   (strnicmp(data, "ignorecase", 10)  == 0)) {
50c2f7538   Steve French   [CIFS] whitespace...
1422
  			vol->nocase = 1;
f636a3480   Jeff Layton   cifs: ignore the ...
1423
1424
1425
1426
1427
1428
  		} 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 ...
1429
1430
  		} else if (strnicmp(data, "brl", 3) == 0) {
  			vol->nobrl =  0;
50c2f7538   Steve French   [CIFS] whitespace...
1431
  		} else if ((strnicmp(data, "nobrl", 5) == 0) ||
1c9551878   Steve French   [CIFS] Add suppor...
1432
  			   (strnicmp(data, "nolock", 6) == 0)) {
c46fa8acd   Steve French   [CIFS] Add mount ...
1433
  			vol->nobrl =  1;
d3485d37c   Steve French   [CIFS] Finish cif...
1434
1435
1436
  			/* turn off mandatory locking in mode
  			if remote locking is turned off since the
  			local vfs will do advisory */
50c2f7538   Steve French   [CIFS] whitespace...
1437
1438
  			if (vol->file_mode ==
  				(S_IALLUGO & ~(S_ISUID | S_IXGRP)))
d3485d37c   Steve French   [CIFS] Finish cif...
1439
  				vol->file_mode = S_IALLUGO;
13a6e42af   Steve French   [CIFS] add mount ...
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
  		} 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
1451
1452
1453
1454
  		} 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...
1455
1456
1457
1458
  		} 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
1459
1460
1461
1462
1463
1464
1465
1466
  		} 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...
1467
1468
1469
1470
  		} 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...
1471
  		} else if (strnicmp(data, "serverino", 7) == 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1472
  			vol->server_ino = 1;
50c2f7538   Steve French   [CIFS] whitespace...
1473
  		} else if (strnicmp(data, "noserverino", 9) == 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1474
  			vol->server_ino = 0;
c9c7fa006   Steve French   Fix the conflict ...
1475
  		} else if (strnicmp(data, "rwpidforward", 12) == 0) {
d4ffff1fa   Pavel Shilovsky   CIFS: Add rwpidfo...
1476
  			vol->rwpidforward = 1;
50c2f7538   Steve French   [CIFS] whitespace...
1477
  		} else if (strnicmp(data, "cifsacl", 7) == 0) {
0a4b92c05   Steve French   [CIFS] Add worker...
1478
1479
1480
  			vol->cifs_acl = 1;
  		} else if (strnicmp(data, "nocifsacl", 9) == 0) {
  			vol->cifs_acl = 0;
50c2f7538   Steve French   [CIFS] whitespace...
1481
  		} else if (strnicmp(data, "acl", 3) == 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1482
  			vol->no_psx_acl = 0;
50c2f7538   Steve French   [CIFS] whitespace...
1483
  		} else if (strnicmp(data, "noacl", 5) == 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1484
  			vol->no_psx_acl = 1;
84210e912   Steve French   [CIFS] improve se...
1485
1486
  		} else if (strnicmp(data, "locallease", 6) == 0) {
  			vol->local_lease = 1;
50c2f7538   Steve French   [CIFS] whitespace...
1487
  		} else if (strnicmp(data, "sign", 4) == 0) {
750d1151a   Steve French   [CIFS] Fix alloca...
1488
  			vol->secFlg |= CIFSSEC_MUST_SIGN;
95b1cb90b   Steve French   [CIFS] enable par...
1489
1490
1491
1492
1493
1494
  		} 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...
1495
  		} else if (strnicmp(data, "direct", 6) == 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1496
  			vol->direct_io = 1;
50c2f7538   Steve French   [CIFS] whitespace...
1497
  		} else if (strnicmp(data, "forcedirectio", 13) == 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1498
  			vol->direct_io = 1;
d39454ffe   Pavel Shilovsky   CIFS: Add strictc...
1499
1500
  		} else if (strnicmp(data, "strictcache", 11) == 0) {
  			vol->strict_io = 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1501
  		} else if (strnicmp(data, "noac", 4) == 0) {
50c2f7538   Steve French   [CIFS] whitespace...
1502
1503
1504
1505
  			printk(KERN_WARNING "CIFS: Mount option noac not "
  				"supported. Instead set "
  				"/proc/fs/cifs/LookupCacheEnabled to 0
  ");
fa1df75d4   Suresh Jayaraman   cifs: add mount o...
1506
  		} else if (strnicmp(data, "fsc", 3) == 0) {
607a569da   Suresh Jayaraman   cifs: allow fsc m...
1507
  #ifndef CONFIG_CIFS_FSCACHE
83fb086e0   Jeff Layton   cifs: trivial: ad...
1508
  			cERROR(1, "FS-Cache support needs CONFIG_CIFS_FSCACHE "
607a569da   Suresh Jayaraman   cifs: allow fsc m...
1509
  				  "kernel config option set");
b946845a9   Sean Finney   cifs: cifs_parse_...
1510
  			goto cifs_parse_mount_err;
607a569da   Suresh Jayaraman   cifs: allow fsc m...
1511
  #endif
fa1df75d4   Suresh Jayaraman   cifs: add mount o...
1512
  			vol->fsc = true;
736a33205   Stefan Metzmacher   cifs: add "mfsyml...
1513
1514
  		} else if (strnicmp(data, "mfsymlinks", 10) == 0) {
  			vol->mfsymlinks = true;
0eb8a132c   Jeff Layton   cifs: add "multiu...
1515
1516
  		} else if (strnicmp(data, "multiuser", 8) == 0) {
  			vol->multiuser = true;
3d3ea8e64   Shirish Pargaonkar   cifs: Add mount o...
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
  		} else if (!strnicmp(data, "backupuid", 9) && value && *value) {
  			err = kstrtouint(value, 0, &vol->backupuid);
  			if (err < 0) {
  				cERROR(1, "%s: Invalid backupuid value",
  					__func__);
  				goto cifs_parse_mount_err;
  			}
  			vol->backupuid_specified = true;
  		} else if (!strnicmp(data, "backupgid", 9) && value && *value) {
  			err = kstrtouint(value, 0, &vol->backupgid);
  			if (err < 0) {
  				cERROR(1, "%s: Invalid backupgid value",
  					__func__);
  				goto cifs_parse_mount_err;
  			}
  			vol->backupgid_specified = true;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1533
  		} else
50c2f7538   Steve French   [CIFS] whitespace...
1534
1535
1536
  			printk(KERN_WARNING "CIFS: Unknown mount option %s
  ",
  						data);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1537
1538
  	}
  	if (vol->UNC == NULL) {
4523cc304   Steve French   [CIFS] UID/GID ov...
1539
  		if (devname == NULL) {
50c2f7538   Steve French   [CIFS] whitespace...
1540
1541
1542
  			printk(KERN_WARNING "CIFS: Missing UNC name for mount "
  						"target
  ");
b946845a9   Sean Finney   cifs: cifs_parse_...
1543
  			goto cifs_parse_mount_err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1544
1545
  		}
  		if ((temp_len = strnlen(devname, 300)) < 300) {
50c2f7538   Steve French   [CIFS] whitespace...
1546
  			vol->UNC = kmalloc(temp_len+1, GFP_KERNEL);
4523cc304   Steve French   [CIFS] UID/GID ov...
1547
  			if (vol->UNC == NULL)
b946845a9   Sean Finney   cifs: cifs_parse_...
1548
  				goto cifs_parse_mount_err;
50c2f7538   Steve French   [CIFS] whitespace...
1549
  			strcpy(vol->UNC, devname);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1550
1551
1552
1553
  			if (strncmp(vol->UNC, "//", 2) == 0) {
  				vol->UNC[0] = '\\';
  				vol->UNC[1] = '\\';
  			} else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
50c2f7538   Steve French   [CIFS] whitespace...
1554
1555
1556
  				printk(KERN_WARNING "CIFS: UNC Path does not "
  						    "begin with // or \\\\ 
  ");
b946845a9   Sean Finney   cifs: cifs_parse_...
1557
  				goto cifs_parse_mount_err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1558
  			}
7c5e628f9   Igor Mammedov   [CIFS] Fixed buil...
1559
1560
1561
  			value = strpbrk(vol->UNC+2, "/\\");
  			if (value)
  				*value = '\\';
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1562
1563
1564
  		} else {
  			printk(KERN_WARNING "CIFS: UNC name too long
  ");
b946845a9   Sean Finney   cifs: cifs_parse_...
1565
  			goto cifs_parse_mount_err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1566
1567
  		}
  	}
0eb8a132c   Jeff Layton   cifs: add "multiu...
1568
1569
1570
1571
  
  	if (vol->multiuser && !(vol->secFlg & CIFSSEC_MAY_KRB5)) {
  		cERROR(1, "Multiuser mounts currently require krb5 "
  			  "authentication!");
b946845a9   Sean Finney   cifs: cifs_parse_...
1572
  		goto cifs_parse_mount_err;
0eb8a132c   Jeff Layton   cifs: add "multiu...
1573
  	}
fb8c4b14d   Steve French   [CIFS] whitespace...
1574
  	if (vol->UNCip == NULL)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1575
  		vol->UNCip = &vol->UNC[2];
9b9d6b243   Jeff Layton   cifs: reinstate o...
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
  	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_...
1589
  	kfree(mountdata_copy);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1590
  	return 0;
b946845a9   Sean Finney   cifs: cifs_parse_...
1591
1592
1593
1594
  
  cifs_parse_mount_err:
  	kfree(mountdata_copy);
  	return 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1595
  }
3eb9a8893   Ben Greear   cifs: Allow bindi...
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
  /** 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...
1621
1622
1623
1624
1625
1626
1627
1628
  /*
   * 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 _...
1629
  	__be16 port, *sport;
4b886136d   Pavel Shilovsky   CIFS: Add match_p...
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
  
  	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...
1655

4515148ef   Jeff Layton   cifs: move addres...
1656
  static bool
3eb9a8893   Ben Greear   cifs: Allow bindi...
1657
1658
  match_address(struct TCP_Server_Info *server, struct sockaddr *addr,
  	      struct sockaddr *srcaddr)
4515148ef   Jeff Layton   cifs: move addres...
1659
  {
4515148ef   Jeff Layton   cifs: move addres...
1660
  	switch (addr->sa_family) {
a9f1b85e5   Pavel Shilovsky   CIFS: Simplify ip...
1661
1662
1663
1664
1665
1666
  	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...
1667
  			return false;
4515148ef   Jeff Layton   cifs: move addres...
1668
  		break;
a9f1b85e5   Pavel Shilovsky   CIFS: Simplify ip...
1669
1670
1671
1672
1673
  	}
  	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...
1674
  		if (!ipv6_addr_equal(&addr6->sin6_addr,
a9f1b85e5   Pavel Shilovsky   CIFS: Simplify ip...
1675
  				     &srv_addr6->sin6_addr))
4515148ef   Jeff Layton   cifs: move addres...
1676
  			return false;
a9f1b85e5   Pavel Shilovsky   CIFS: Simplify ip...
1677
  		if (addr6->sin6_scope_id != srv_addr6->sin6_scope_id)
4515148ef   Jeff Layton   cifs: move addres...
1678
  			return false;
4515148ef   Jeff Layton   cifs: move addres...
1679
1680
  		break;
  	}
a9f1b85e5   Pavel Shilovsky   CIFS: Simplify ip...
1681
1682
1683
1684
  	default:
  		WARN_ON(1);
  		return false; /* don't expect to be here */
  	}
4515148ef   Jeff Layton   cifs: move addres...
1685

3eb9a8893   Ben Greear   cifs: Allow bindi...
1686
1687
  	if (!srcip_matches(srcaddr, (struct sockaddr *)&server->srcaddr))
  		return false;
4515148ef   Jeff Layton   cifs: move addres...
1688
1689
  	return true;
  }
daf5b0b6f   Jeff Layton   cifs: match secTy...
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
  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...
1725
  	/* now check if signing mode is acceptable */
daf5b0b6f   Jeff Layton   cifs: match secTy...
1726
  	if ((secFlags & CIFSSEC_MAY_SIGN) == 0 &&
96daf2b09   Steve French   [CIFS] Rename thr...
1727
  	    (server->sec_mode & SECMODE_SIGN_REQUIRED))
daf5b0b6f   Jeff Layton   cifs: match secTy...
1728
1729
  			return false;
  	else if (((secFlags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN) &&
96daf2b09   Steve French   [CIFS] Rename thr...
1730
  		 (server->sec_mode &
daf5b0b6f   Jeff Layton   cifs: match secTy...
1731
1732
1733
1734
1735
  		  (SECMODE_SIGN_ENABLED|SECMODE_SIGN_REQUIRED)) == 0)
  			return false;
  
  	return true;
  }
37bb04e5a   Pavel Shilovsky   CIFS: Simplify co...
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
  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...
1754
  static struct TCP_Server_Info *
daf5b0b6f   Jeff Layton   cifs: match secTy...
1755
  cifs_find_tcp_session(struct sockaddr *addr, struct smb_vol *vol)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1756
  {
e7ddee903   Jeff Layton   cifs: disable sha...
1757
  	struct TCP_Server_Info *server;
e7ddee903   Jeff Layton   cifs: disable sha...
1758

3f9bcca78   Suresh Jayaraman   cifs: convert cif...
1759
  	spin_lock(&cifs_tcp_ses_lock);
4515148ef   Jeff Layton   cifs: move addres...
1760
  	list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) {
37bb04e5a   Pavel Shilovsky   CIFS: Simplify co...
1761
  		if (!match_server(server, addr, vol))
daf5b0b6f   Jeff Layton   cifs: match secTy...
1762
  			continue;
e7ddee903   Jeff Layton   cifs: disable sha...
1763
  		++server->srv_count;
3f9bcca78   Suresh Jayaraman   cifs: convert cif...
1764
  		spin_unlock(&cifs_tcp_ses_lock);
b6b38f704   Joe Perches   [CIFS] Neaten cER...
1765
  		cFYI(1, "Existing tcp session with server found");
e7ddee903   Jeff Layton   cifs: disable sha...
1766
  		return server;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1767
  	}
3f9bcca78   Suresh Jayaraman   cifs: convert cif...
1768
  	spin_unlock(&cifs_tcp_ses_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1769
1770
  	return NULL;
  }
1b20d6721   Cyrill Gorcunov   [CIFS] cifs_find_...
1771

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

3f9bcca78   Suresh Jayaraman   cifs: convert cif...
1777
  	spin_lock(&cifs_tcp_ses_lock);
e7ddee903   Jeff Layton   cifs: disable sha...
1778
  	if (--server->srv_count > 0) {
3f9bcca78   Suresh Jayaraman   cifs: convert cif...
1779
  		spin_unlock(&cifs_tcp_ses_lock);
e7ddee903   Jeff Layton   cifs: disable sha...
1780
  		return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1781
  	}
1b20d6721   Cyrill Gorcunov   [CIFS] cifs_find_...
1782

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

c74093b69   Jeff Layton   cifs: set up recu...
1787
  	cancel_delayed_work_sync(&server->echo);
e7ddee903   Jeff Layton   cifs: disable sha...
1788
1789
1790
  	spin_lock(&GlobalMid_Lock);
  	server->tcpStatus = CifsExiting;
  	spin_unlock(&GlobalMid_Lock);
dea570e08   Steve French   [CIFS] Remove ove...
1791

d2b915210   Shirish Pargaonkar   NTLM auth and sig...
1792
  	cifs_crypto_shash_release(server);
488f1d2d6   Suresh Jayaraman   cifs: define serv...
1793
  	cifs_fscache_release_client_cookie(server);
21e733930   Shirish Pargaonkar   NTLM auth and sig...
1794
1795
1796
  	kfree(server->session_key.response);
  	server->session_key.response = NULL;
  	server->session_key.len = 0;
e7ddee903   Jeff Layton   cifs: disable sha...
1797
1798
1799
  	task = xchg(&server->tsk, NULL);
  	if (task)
  		force_sig(SIGKILL, task);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1800
  }
63c038c29   Jeff Layton   cifs: move alloca...
1801
1802
1803
1804
  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...
1805
  	struct sockaddr_storage addr;
63c038c29   Jeff Layton   cifs: move alloca...
1806
1807
1808
  	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...
1809
  	memset(&addr, 0, sizeof(struct sockaddr_storage));
63c038c29   Jeff Layton   cifs: move alloca...
1810

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

1e68b2b27   Jeff Layton   cifs: add new rou...
1813
  	if (volume_info->UNCip && volume_info->UNC) {
50d971602   Jeff Layton   cifs: set the por...
1814
1815
  		rc = cifs_fill_sockaddr((struct sockaddr *)&addr,
  					volume_info->UNCip,
67b7626a0   David Howells   CIFS: Make cifs_c...
1816
  					strlen(volume_info->UNCip),
50d971602   Jeff Layton   cifs: set the por...
1817
  					volume_info->port);
1e68b2b27   Jeff Layton   cifs: add new rou...
1818
  		if (!rc) {
63c038c29   Jeff Layton   cifs: move alloca...
1819
1820
1821
1822
  			/* we failed translating address */
  			rc = -EINVAL;
  			goto out_err;
  		}
63c038c29   Jeff Layton   cifs: move alloca...
1823
1824
1825
  	} 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...
1826
  		cERROR(1, "Connecting to DFS root not implemented yet");
63c038c29   Jeff Layton   cifs: move alloca...
1827
1828
1829
  		rc = -EINVAL;
  		goto out_err;
  	} else /* which tcp_sess DFS root would we conect to */ {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
1830
1831
  		cERROR(1, "CIFS mount error: No UNC path (e.g. -o "
  			"unc=//192.168.1.100/public) specified");
63c038c29   Jeff Layton   cifs: move alloca...
1832
1833
1834
1835
1836
  		rc = -EINVAL;
  		goto out_err;
  	}
  
  	/* see if we already have a matching tcp_ses */
daf5b0b6f   Jeff Layton   cifs: match secTy...
1837
  	tcp_ses = cifs_find_tcp_session((struct sockaddr *)&addr, volume_info);
63c038c29   Jeff Layton   cifs: move alloca...
1838
1839
1840
1841
1842
1843
1844
1845
  	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...
1846
1847
1848
1849
1850
  	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...
1851
  	cifs_set_net_ns(tcp_ses, get_net(current->nsproxy->net_ns));
63c038c29   Jeff Layton   cifs: move alloca...
1852
1853
1854
  	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...
1855
  		goto out_err_crypto_release;
63c038c29   Jeff Layton   cifs: move alloca...
1856
1857
1858
1859
  	}
  
  	tcp_ses->noblocksnd = volume_info->noblocksnd;
  	tcp_ses->noautotune = volume_info->noautotune;
6a5fa2362   Steve French   [CIFS] Add suppor...
1860
  	tcp_ses->tcp_nodelay = volume_info->sockopt_tcp_nodelay;
63c038c29   Jeff Layton   cifs: move alloca...
1861
1862
1863
1864
1865
1866
1867
1868
1869
  	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...
1870
  	tcp_ses->session_estab = false;
63c038c29   Jeff Layton   cifs: move alloca...
1871
  	tcp_ses->sequence_number = 0;
fda359436   Steve French   [CIFS] cifs: reco...
1872
  	tcp_ses->lstrp = jiffies;
63c038c29   Jeff Layton   cifs: move alloca...
1873
1874
  	INIT_LIST_HEAD(&tcp_ses->tcp_ses_list);
  	INIT_LIST_HEAD(&tcp_ses->smb_ses_list);
c74093b69   Jeff Layton   cifs: set up recu...
1875
  	INIT_DELAYED_WORK(&tcp_ses->echo, cifs_echo_request);
63c038c29   Jeff Layton   cifs: move alloca...
1876
1877
1878
1879
1880
1881
1882
  
  	/*
  	 * 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...
1883
1884
  	memcpy(&tcp_ses->srcaddr, &volume_info->srcaddr,
  	       sizeof(tcp_ses->srcaddr));
63c038c29   Jeff Layton   cifs: move alloca...
1885
  	++tcp_ses->srv_count;
a9ac49d30   Jeff Layton   cifs: make sure w...
1886
  	if (addr.ss_family == AF_INET6) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
1887
  		cFYI(1, "attempting ipv6 connect");
63c038c29   Jeff Layton   cifs: move alloca...
1888
1889
  		/* BB should we allow ipv6 on port 139? */
  		/* other OS never observed in Wild doing 139 with v6 */
a9f1b85e5   Pavel Shilovsky   CIFS: Simplify ip...
1890
1891
1892
1893
1894
1895
1896
  		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...
1897
  	if (rc < 0) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
1898
  		cERROR(1, "Error connecting to socket. Aborting operation");
f7c5445a9   Shirish Pargaonkar   NTLM auth and sig...
1899
  		goto out_err_crypto_release;
63c038c29   Jeff Layton   cifs: move alloca...
1900
1901
1902
1903
1904
1905
1906
  	}
  
  	/*
  	 * 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...
1907
  	tcp_ses->tsk = kthread_run(cifs_demultiplex_thread,
63c038c29   Jeff Layton   cifs: move alloca...
1908
1909
1910
  				  tcp_ses, "cifsd");
  	if (IS_ERR(tcp_ses->tsk)) {
  		rc = PTR_ERR(tcp_ses->tsk);
b6b38f704   Joe Perches   [CIFS] Neaten cER...
1911
  		cERROR(1, "error %d create cifsd thread", rc);
63c038c29   Jeff Layton   cifs: move alloca...
1912
  		module_put(THIS_MODULE);
f7c5445a9   Shirish Pargaonkar   NTLM auth and sig...
1913
  		goto out_err_crypto_release;
63c038c29   Jeff Layton   cifs: move alloca...
1914
  	}
fd88ce931   Steve French   [CIFS] cifs: clar...
1915
  	tcp_ses->tcpStatus = CifsNeedNegotiate;
63c038c29   Jeff Layton   cifs: move alloca...
1916
1917
  
  	/* thread spawned, put it on the list */
3f9bcca78   Suresh Jayaraman   cifs: convert cif...
1918
  	spin_lock(&cifs_tcp_ses_lock);
63c038c29   Jeff Layton   cifs: move alloca...
1919
  	list_add(&tcp_ses->tcp_ses_list, &cifs_tcp_ses_list);
3f9bcca78   Suresh Jayaraman   cifs: convert cif...
1920
  	spin_unlock(&cifs_tcp_ses_lock);
63c038c29   Jeff Layton   cifs: move alloca...
1921

488f1d2d6   Suresh Jayaraman   cifs: define serv...
1922
  	cifs_fscache_get_client_cookie(tcp_ses);
c74093b69   Jeff Layton   cifs: set up recu...
1923
1924
  	/* queue echo request delayed work */
  	queue_delayed_work(system_nrt_wq, &tcp_ses->echo, SMB_ECHO_INTERVAL);
63c038c29   Jeff Layton   cifs: move alloca...
1925
  	return tcp_ses;
f7c5445a9   Shirish Pargaonkar   NTLM auth and sig...
1926
  out_err_crypto_release:
d2b915210   Shirish Pargaonkar   NTLM auth and sig...
1927
  	cifs_crypto_shash_release(tcp_ses);
f1d0c9986   Rob Landley   Make CIFS mount w...
1928
  	put_net(cifs_net_ns(tcp_ses));
63c038c29   Jeff Layton   cifs: move alloca...
1929
1930
  out_err:
  	if (tcp_ses) {
8347a5cdd   Steve French   [CIFS] Fixing to ...
1931
1932
  		if (!IS_ERR(tcp_ses->hostname))
  			kfree(tcp_ses->hostname);
63c038c29   Jeff Layton   cifs: move alloca...
1933
1934
1935
1936
1937
1938
  		if (tcp_ses->ssocket)
  			sock_release(tcp_ses->ssocket);
  		kfree(tcp_ses);
  	}
  	return ERR_PTR(rc);
  }
96daf2b09   Steve French   [CIFS] Rename thr...
1939
  static int match_session(struct cifs_ses *ses, struct smb_vol *vol)
37bb04e5a   Pavel Shilovsky   CIFS: Simplify co...
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
  {
  	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...
1962
  static struct cifs_ses *
4ff67b720   Jeff Layton   cifs: clean up ci...
1963
  cifs_find_smb_ses(struct TCP_Server_Info *server, struct smb_vol *vol)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1964
  {
96daf2b09   Steve French   [CIFS] Rename thr...
1965
  	struct cifs_ses *ses;
dea570e08   Steve French   [CIFS] Remove ove...
1966

3f9bcca78   Suresh Jayaraman   cifs: convert cif...
1967
  	spin_lock(&cifs_tcp_ses_lock);
4ff67b720   Jeff Layton   cifs: clean up ci...
1968
  	list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
37bb04e5a   Pavel Shilovsky   CIFS: Simplify co...
1969
1970
  		if (!match_session(ses, vol))
  			continue;
14fbf50d6   Jeff Layton   cifs: reinstate s...
1971
  		++ses->ses_count;
3f9bcca78   Suresh Jayaraman   cifs: convert cif...
1972
  		spin_unlock(&cifs_tcp_ses_lock);
14fbf50d6   Jeff Layton   cifs: reinstate s...
1973
1974
  		return ses;
  	}
3f9bcca78   Suresh Jayaraman   cifs: convert cif...
1975
  	spin_unlock(&cifs_tcp_ses_lock);
14fbf50d6   Jeff Layton   cifs: reinstate s...
1976
1977
  	return NULL;
  }
dea570e08   Steve French   [CIFS] Remove ove...
1978

14fbf50d6   Jeff Layton   cifs: reinstate s...
1979
  static void
96daf2b09   Steve French   [CIFS] Rename thr...
1980
  cifs_put_smb_ses(struct cifs_ses *ses)
14fbf50d6   Jeff Layton   cifs: reinstate s...
1981
1982
1983
  {
  	int xid;
  	struct TCP_Server_Info *server = ses->server;
dea570e08   Steve French   [CIFS] Remove ove...
1984

36988c76f   Jeff Layton   cifs: move SMB se...
1985
1986
  	cFYI(1, "%s: ses_count=%d
  ", __func__, ses->ses_count);
3f9bcca78   Suresh Jayaraman   cifs: convert cif...
1987
  	spin_lock(&cifs_tcp_ses_lock);
14fbf50d6   Jeff Layton   cifs: reinstate s...
1988
  	if (--ses->ses_count > 0) {
3f9bcca78   Suresh Jayaraman   cifs: convert cif...
1989
  		spin_unlock(&cifs_tcp_ses_lock);
14fbf50d6   Jeff Layton   cifs: reinstate s...
1990
1991
  		return;
  	}
dea570e08   Steve French   [CIFS] Remove ove...
1992

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

14fbf50d6   Jeff Layton   cifs: reinstate s...
1996
1997
1998
1999
2000
2001
2002
2003
  	if (ses->status == CifsGood) {
  		xid = GetXid();
  		CIFSSMBLogoff(xid, ses);
  		_FreeXid(xid);
  	}
  	sesInfoFree(ses);
  	cifs_put_tcp_session(server);
  }
dea570e08   Steve French   [CIFS] Remove ove...
2004

d9b942013   Steve French   [CIFS] Warn on re...
2005
  static bool warned_on_ntlm;  /* globals init to false automatically */
96daf2b09   Steve French   [CIFS] Rename thr...
2006
  static struct cifs_ses *
36988c76f   Jeff Layton   cifs: move SMB se...
2007
2008
2009
  cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
  {
  	int rc = -ENOMEM, xid;
96daf2b09   Steve French   [CIFS] Rename thr...
2010
  	struct cifs_ses *ses;
a9f1b85e5   Pavel Shilovsky   CIFS: Simplify ip...
2011
2012
  	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...
2013
2014
  
  	xid = GetXid();
4ff67b720   Jeff Layton   cifs: clean up ci...
2015
  	ses = cifs_find_smb_ses(server, volume_info);
36988c76f   Jeff Layton   cifs: move SMB se...
2016
2017
  	if (ses) {
  		cFYI(1, "Existing smb sess found (status=%d)", ses->status);
36988c76f   Jeff Layton   cifs: move SMB se...
2018
  		mutex_lock(&ses->session_mutex);
198b56827   Jeff Layton   cifs: break negot...
2019
2020
2021
2022
2023
2024
2025
2026
  		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...
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
  		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...
2040
2041
2042
  
  		/* existing SMB ses has a server reference already */
  		cifs_put_tcp_session(server);
36988c76f   Jeff Layton   cifs: move SMB se...
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
  		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...
2054
2055
  	if (server->dstaddr.ss_family == AF_INET6)
  		sprintf(ses->serverName, "%pI6", &addr6->sin6_addr);
36988c76f   Jeff Layton   cifs: move SMB se...
2056
  	else
a9f1b85e5   Pavel Shilovsky   CIFS: Simplify ip...
2057
  		sprintf(ses->serverName, "%pI4", &addr->sin_addr);
36988c76f   Jeff Layton   cifs: move SMB se...
2058

8727c8a85   Steve French   Allow user names ...
2059
2060
2061
2062
2063
  	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...
2064
2065
2066
2067
2068
2069
2070
2071
  
  	/* 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...
2072
2073
2074
  		ses->domainName = kstrdup(volume_info->domainname, GFP_KERNEL);
  		if (!ses->domainName)
  			goto get_ses_fail;
36988c76f   Jeff Layton   cifs: move SMB se...
2075
  	}
3e4b3e1f6   Jeff Layton   cifs: add separat...
2076
  	ses->cred_uid = volume_info->cred_uid;
36988c76f   Jeff Layton   cifs: move SMB se...
2077
  	ses->linux_uid = volume_info->linux_uid;
d9b942013   Steve French   [CIFS] Warn on re...
2078
2079
2080
2081
2082
2083
2084
  
  	/* 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 "
225de11e3   Steve French   [CIFS] default nt...
2085
  			"ntlmv2 in kernel release 3.3");
d9b942013   Steve French   [CIFS] Warn on re...
2086
  	}
36988c76f   Jeff Layton   cifs: move SMB se...
2087
2088
2089
  	ses->overrideSecFlg = volume_info->secFlg;
  
  	mutex_lock(&ses->session_mutex);
198b56827   Jeff Layton   cifs: break negot...
2090
2091
2092
  	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...
2093
  	mutex_unlock(&ses->session_mutex);
c8e56f1f4   Steve French   Revert "[CIFS] Fi...
2094
  	if (rc)
36988c76f   Jeff Layton   cifs: move SMB se...
2095
2096
2097
  		goto get_ses_fail;
  
  	/* success, put it on the list */
3f9bcca78   Suresh Jayaraman   cifs: convert cif...
2098
  	spin_lock(&cifs_tcp_ses_lock);
36988c76f   Jeff Layton   cifs: move SMB se...
2099
  	list_add(&ses->smb_ses_list, &server->smb_ses_list);
3f9bcca78   Suresh Jayaraman   cifs: convert cif...
2100
  	spin_unlock(&cifs_tcp_ses_lock);
36988c76f   Jeff Layton   cifs: move SMB se...
2101
2102
2103
2104
2105
2106
2107
2108
2109
  
  	FreeXid(xid);
  	return ses;
  
  get_ses_fail:
  	sesInfoFree(ses);
  	FreeXid(xid);
  	return ERR_PTR(rc);
  }
96daf2b09   Steve French   [CIFS] Rename thr...
2110
  static int match_tcon(struct cifs_tcon *tcon, const char *unc)
37bb04e5a   Pavel Shilovsky   CIFS: Simplify co...
2111
2112
2113
2114
2115
2116
2117
  {
  	if (tcon->tidStatus == CifsExiting)
  		return 0;
  	if (strncmp(tcon->treeName, unc, MAX_TREE_SIZE))
  		return 0;
  	return 1;
  }
96daf2b09   Steve French   [CIFS] Rename thr...
2118
2119
  static struct cifs_tcon *
  cifs_find_tcon(struct cifs_ses *ses, const char *unc)
f1987b44f   Jeff Layton   cifs: reinstate s...
2120
2121
  {
  	struct list_head *tmp;
96daf2b09   Steve French   [CIFS] Rename thr...
2122
  	struct cifs_tcon *tcon;
f1987b44f   Jeff Layton   cifs: reinstate s...
2123

3f9bcca78   Suresh Jayaraman   cifs: convert cif...
2124
  	spin_lock(&cifs_tcp_ses_lock);
f1987b44f   Jeff Layton   cifs: reinstate s...
2125
  	list_for_each(tmp, &ses->tcon_list) {
96daf2b09   Steve French   [CIFS] Rename thr...
2126
  		tcon = list_entry(tmp, struct cifs_tcon, tcon_list);
37bb04e5a   Pavel Shilovsky   CIFS: Simplify co...
2127
  		if (!match_tcon(tcon, unc))
f1987b44f   Jeff Layton   cifs: reinstate s...
2128
  			continue;
f1987b44f   Jeff Layton   cifs: reinstate s...
2129
  		++tcon->tc_count;
3f9bcca78   Suresh Jayaraman   cifs: convert cif...
2130
  		spin_unlock(&cifs_tcp_ses_lock);
dea570e08   Steve French   [CIFS] Remove ove...
2131
  		return tcon;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2132
  	}
3f9bcca78   Suresh Jayaraman   cifs: convert cif...
2133
  	spin_unlock(&cifs_tcp_ses_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2134
2135
  	return NULL;
  }
f1987b44f   Jeff Layton   cifs: reinstate s...
2136
  static void
96daf2b09   Steve French   [CIFS] Rename thr...
2137
  cifs_put_tcon(struct cifs_tcon *tcon)
f1987b44f   Jeff Layton   cifs: reinstate s...
2138
2139
  {
  	int xid;
96daf2b09   Steve French   [CIFS] Rename thr...
2140
  	struct cifs_ses *ses = tcon->ses;
f1987b44f   Jeff Layton   cifs: reinstate s...
2141

d00c28de5   Jeff Layton   cifs: move tcon f...
2142
2143
  	cFYI(1, "%s: tc_count=%d
  ", __func__, tcon->tc_count);
3f9bcca78   Suresh Jayaraman   cifs: convert cif...
2144
  	spin_lock(&cifs_tcp_ses_lock);
f1987b44f   Jeff Layton   cifs: reinstate s...
2145
  	if (--tcon->tc_count > 0) {
3f9bcca78   Suresh Jayaraman   cifs: convert cif...
2146
  		spin_unlock(&cifs_tcp_ses_lock);
f1987b44f   Jeff Layton   cifs: reinstate s...
2147
2148
2149
2150
  		return;
  	}
  
  	list_del_init(&tcon->tcon_list);
3f9bcca78   Suresh Jayaraman   cifs: convert cif...
2151
  	spin_unlock(&cifs_tcp_ses_lock);
f1987b44f   Jeff Layton   cifs: reinstate s...
2152
2153
2154
2155
  
  	xid = GetXid();
  	CIFSSMBTDis(xid, tcon);
  	_FreeXid(xid);
d03382ce9   Suresh Jayaraman   cifs: define supe...
2156
  	cifs_fscache_release_super_cookie(tcon);
9f841593f   Steve French   [CIFS] relinquish...
2157
  	tconInfoFree(tcon);
f1987b44f   Jeff Layton   cifs: reinstate s...
2158
2159
  	cifs_put_smb_ses(ses);
  }
96daf2b09   Steve French   [CIFS] Rename thr...
2160
2161
  static struct cifs_tcon *
  cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
d00c28de5   Jeff Layton   cifs: move tcon f...
2162
2163
  {
  	int rc, xid;
96daf2b09   Steve French   [CIFS] Rename thr...
2164
  	struct cifs_tcon *tcon;
d00c28de5   Jeff Layton   cifs: move tcon f...
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
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
  
  	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...
2221
  	spin_lock(&cifs_tcp_ses_lock);
d00c28de5   Jeff Layton   cifs: move tcon f...
2222
  	list_add(&tcon->tcon_list, &ses->tcon_list);
3f9bcca78   Suresh Jayaraman   cifs: convert cif...
2223
  	spin_unlock(&cifs_tcp_ses_lock);
d00c28de5   Jeff Layton   cifs: move tcon f...
2224

d03382ce9   Suresh Jayaraman   cifs: define supe...
2225
  	cifs_fscache_get_super_cookie(tcon);
d00c28de5   Jeff Layton   cifs: move tcon f...
2226
2227
2228
2229
2230
2231
  	return tcon;
  
  out_fail:
  	tconInfoFree(tcon);
  	return ERR_PTR(rc);
  }
9d002df49   Jeff Layton   cifs: add routine...
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
  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...
2249

25c7f41e9   Pavel Shilovsky   CIFS: Migrate to ...
2250
  static inline struct tcon_link *
cd51875d5   Pavel Shilovsky   CIFS: Fix sparse ...
2251
2252
2253
2254
  cifs_sb_master_tlink(struct cifs_sb_info *cifs_sb)
  {
  	return cifs_sb->master_tlink;
  }
25c7f41e9   Pavel Shilovsky   CIFS: Migrate to ...
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
  
  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;
25c7f41e9   Pavel Shilovsky   CIFS: Migrate to ...
2268
  	/*
5eba8ab36   Jeff Layton   cifs: allow for l...
2269
2270
  	 * We want to share sb only if we don't specify an r/wsize or
  	 * specified r/wsize is greater than or equal to existing one.
25c7f41e9   Pavel Shilovsky   CIFS: Migrate to ...
2271
2272
2273
  	 */
  	if (new->wsize && new->wsize < old->wsize)
  		return 0;
5eba8ab36   Jeff Layton   cifs: allow for l...
2274
2275
  	if (new->rsize && new->rsize < old->rsize)
  		return 0;
25c7f41e9   Pavel Shilovsky   CIFS: Migrate to ...
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
  	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...
2299
2300
  	struct cifs_ses *ses;
  	struct cifs_tcon *tcon;
25c7f41e9   Pavel Shilovsky   CIFS: Migrate to ...
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
  	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 ...
2339
  	spin_unlock(&cifs_tcp_ses_lock);
f484b5d00   Jeff Layton   cifs: drop spinlo...
2340
  	cifs_put_tlink(tlink);
25c7f41e9   Pavel Shilovsky   CIFS: Migrate to ...
2341
2342
  	return rc;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2343
  int
96daf2b09   Steve French   [CIFS] Rename thr...
2344
  get_dfs_path(int xid, struct cifs_ses *pSesInfo, const char *old_path,
50c2f7538   Steve French   [CIFS] whitespace...
2345
  	     const struct nls_table *nls_codepage, unsigned int *pnum_referrals,
366781c19   Steve French   [CIFS] DFS build ...
2346
  	     struct dfs_info3_param **preferrals, int remap)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2347
2348
2349
2350
2351
  {
  	char *temp_unc;
  	int rc = 0;
  
  	*pnum_referrals = 0;
366781c19   Steve French   [CIFS] DFS build ...
2352
  	*preferrals = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2353
2354
2355
  
  	if (pSesInfo->ipc_tid == 0) {
  		temp_unc = kmalloc(2 /* for slashes */ +
50c2f7538   Steve French   [CIFS] whitespace...
2356
2357
  			strnlen(pSesInfo->serverName,
  				SERVER_NAME_LEN_WITH_NULL * 2)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2358
2359
2360
2361
2362
2363
2364
2365
2366
  				 + 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...
2367
  		cFYI(1, "CIFS Tcon rc = %d ipc_tid = %d", rc, pSesInfo->ipc_tid);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2368
2369
2370
  		kfree(temp_unc);
  	}
  	if (rc == 0)
c2cf07d59   Steve French   [CIFS] Finishup D...
2371
  		rc = CIFSGetDFSRefer(xid, pSesInfo, old_path, preferrals,
737b758c9   Steve French   [PATCH] cifs: cha...
2372
  				     pnum_referrals, nls_codepage, remap);
366781c19   Steve French   [CIFS] DFS build ...
2373
2374
  	/* BB map targetUNCs to dfs_info3 structures, here or
  		in CIFSGetDFSRefer BB */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2375
2376
2377
  
  	return rc;
  }
09e50d55a   Jeff Layton   lockdep: annotate...
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
  #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
2410
  /* See RFC1001 section 14 on representation of Netbios names */
50c2f7538   Steve French   [CIFS] whitespace...
2411
  static void rfc1002mangle(char *target, char *source, unsigned int length)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2412
  {
50c2f7538   Steve French   [CIFS] whitespace...
2413
  	unsigned int i, j;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2414

50c2f7538   Steve French   [CIFS] whitespace...
2415
  	for (i = 0, j = 0; i < (length); i++) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2416
2417
2418
  		/* 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...
2419
  		j += 2;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2420
2421
2422
  	}
  
  }
3eb9a8893   Ben Greear   cifs: Allow bindi...
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
  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
2452
2453
  
  static int
a9f1b85e5   Pavel Shilovsky   CIFS: Simplify ip...
2454
  ip_rfc1001_connect(struct TCP_Server_Info *server)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2455
2456
  {
  	int rc = 0;
a9f1b85e5   Pavel Shilovsky   CIFS: Simplify ip...
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
  	/*
  	 * 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 ...
2504
  		smb_buf->smb_buf_length = cpu_to_be32(0x81000044);
a9f1b85e5   Pavel Shilovsky   CIFS: Simplify ip...
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
  		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 _...
2531
  	__be16 sport;
a9f1b85e5   Pavel Shilovsky   CIFS: Simplify ip...
2532
  	int slen, sfamily;
bcf4b1063   Jeff Layton   cifs: make ipv4_c...
2533
  	struct socket *socket = server->ssocket;
a9f1b85e5   Pavel Shilovsky   CIFS: Simplify ip...
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
  	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
2547

bcf4b1063   Jeff Layton   cifs: make ipv4_c...
2548
  	if (socket == NULL) {
f1d0c9986   Rob Landley   Make CIFS mount w...
2549
2550
  		rc = __sock_create(cifs_net_ns(server), sfamily, SOCK_STREAM,
  				   IPPROTO_TCP, &socket, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2551
  		if (rc < 0) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
2552
  			cERROR(1, "Error %d creating socket", rc);
a9f1b85e5   Pavel Shilovsky   CIFS: Simplify ip...
2553
  			server->ssocket = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2554
  			return rc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2555
  		}
bcf4b1063   Jeff Layton   cifs: make ipv4_c...
2556
2557
  
  		/* BB other socket options to set KEEPALIVE, NODELAY? */
b6b38f704   Joe Perches   [CIFS] Neaten cER...
2558
  		cFYI(1, "Socket created");
bcf4b1063   Jeff Layton   cifs: make ipv4_c...
2559
2560
  		server->ssocket = socket;
  		socket->sk->sk_allocation = GFP_NOFS;
a9f1b85e5   Pavel Shilovsky   CIFS: Simplify ip...
2561
2562
2563
2564
  		if (sfamily == AF_INET6)
  			cifs_reclassify_socket6(socket);
  		else
  			cifs_reclassify_socket4(socket);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2565
  	}
3eb9a8893   Ben Greear   cifs: Allow bindi...
2566
2567
2568
  	rc = bind_socket(server);
  	if (rc < 0)
  		return rc;
bcf4b1063   Jeff Layton   cifs: make ipv4_c...
2569
2570
  	/*
  	 * Eventually check for other socket options to change from
a9f1b85e5   Pavel Shilovsky   CIFS: Simplify ip...
2571
2572
  	 * the default. sock_setsockopt not used because it expects
  	 * user space buffer
bcf4b1063   Jeff Layton   cifs: make ipv4_c...
2573
2574
  	 */
  	socket->sk->sk_rcvtimeo = 7 * HZ;
da505c386   Steve French   [CIFS] Make socke...
2575
  	socket->sk->sk_sndtimeo = 5 * HZ;
edf1ae403   Steve French   [CIFS] Reduce num...
2576

b387eaeb6   Steve French   [CIFS] Do not shr...
2577
  	/* make the bufsizes depend on wsize/rsize and max requests */
bcf4b1063   Jeff Layton   cifs: make ipv4_c...
2578
2579
2580
2581
2582
  	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...
2583
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2584

6a5fa2362   Steve French   [CIFS] Add suppor...
2585
  	if (server->tcp_nodelay) {
a9f1b85e5   Pavel Shilovsky   CIFS: Simplify ip...
2586
  		int val = 1;
6a5fa2362   Steve French   [CIFS] Add suppor...
2587
2588
2589
  		rc = kernel_setsockopt(socket, SOL_TCP, TCP_NODELAY,
  				(char *)&val, sizeof(val));
  		if (rc)
b6b38f704   Joe Perches   [CIFS] Neaten cER...
2590
  			cFYI(1, "set TCP_NODELAY socket option error %d", rc);
6a5fa2362   Steve French   [CIFS] Add suppor...
2591
  	}
b6b38f704   Joe Perches   [CIFS] Neaten cER...
2592
  	 cFYI(1, "sndbuf %d rcvbuf %d rcvtimeo 0x%lx",
bcf4b1063   Jeff Layton   cifs: make ipv4_c...
2593
  		 socket->sk->sk_sndbuf,
b6b38f704   Joe Perches   [CIFS] Neaten cER...
2594
  		 socket->sk->sk_rcvbuf, socket->sk->sk_rcvtimeo);
bcf4b1063   Jeff Layton   cifs: make ipv4_c...
2595

ee1b3ea9e   Jeff Layton   cifs: set socket ...
2596
2597
2598
2599
2600
2601
2602
  	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...
2603
2604
  	if (sport == htons(RFC1001_PORT))
  		rc = ip_rfc1001_connect(server);
50c2f7538   Steve French   [CIFS] whitespace...
2605

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2606
2607
2608
2609
  	return rc;
  }
  
  static int
a9f1b85e5   Pavel Shilovsky   CIFS: Simplify ip...
2610
  ip_connect(struct TCP_Server_Info *server)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2611
  {
6da979106   Steve French   Elminate sparse _...
2612
  	__be16 *sport;
a9f1b85e5   Pavel Shilovsky   CIFS: Simplify ip...
2613
2614
  	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
2615

a9f1b85e5   Pavel Shilovsky   CIFS: Simplify ip...
2616
2617
2618
2619
  	if (server->dstaddr.ss_family == AF_INET6)
  		sport = &addr6->sin6_port;
  	else
  		sport = &addr->sin_port;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2620

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

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

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

a9f1b85e5   Pavel Shilovsky   CIFS: Simplify ip...
2631
2632
  		/* if it failed, try with 139 port */
  		*sport = htons(RFC1001_PORT);
6a5fa2362   Steve French   [CIFS] Add suppor...
2633
  	}
a9f1b85e5   Pavel Shilovsky   CIFS: Simplify ip...
2634
  	return generic_ip_connect(server);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2635
  }
96daf2b09   Steve French   [CIFS] Rename thr...
2636
  void reset_cifs_unix_caps(int xid, struct cifs_tcon *tcon,
2c6292ae4   Al Viro   cifs: don't pass ...
2637
  			  struct cifs_sb_info *cifs_sb, struct smb_vol *vol_info)
8af189715   Steve French   [CIFS] on reconne...
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
  {
  	/* 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...
2649

c18c842b1   Steve French   [CIFS] Allow disa...
2650
2651
2652
  	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...
2653
  		cFYI(1, "Linux protocol extensions disabled");
c18c842b1   Steve French   [CIFS] Allow disa...
2654
2655
2656
2657
2658
  		return;
  	} else if (vol_info)
  		tcon->unix_ext = 1; /* Unix Extensions supported */
  
  	if (tcon->unix_ext == 0) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
2659
  		cFYI(1, "Unix extensions disabled so not set on reconnect");
c18c842b1   Steve French   [CIFS] Allow disa...
2660
2661
  		return;
  	}
50c2f7538   Steve French   [CIFS] whitespace...
2662

fb8c4b14d   Steve French   [CIFS] whitespace...
2663
  	if (!CIFSSMBQFSUnixInfo(xid, tcon)) {
8af189715   Steve French   [CIFS] on reconne...
2664
  		__u64 cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
6848b7334   Steve French   [CIFS] When manda...
2665
  		cFYI(1, "unix caps which server supports %lld", cap);
8af189715   Steve French   [CIFS] on reconne...
2666
2667
  		/* 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...
2668
  		if (vol_info == NULL) {
50c2f7538   Steve French   [CIFS] whitespace...
2669
  			/* turn off POSIX ACL and PATHNAMES if not set
8af189715   Steve French   [CIFS] on reconne...
2670
2671
2672
  			   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...
2673
2674
  			if ((saved_cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) {
  				if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
b6b38f704   Joe Perches   [CIFS] Neaten cER...
2675
  					cERROR(1, "POSIXPATH support change");
8af189715   Steve French   [CIFS] on reconne...
2676
  				cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
11b6d6450   Igor Mammedov   [CIFS] Only conve...
2677
  			} else if ((cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
2678
2679
  				cERROR(1, "possible reconnect error");
  				cERROR(1, "server disabled POSIX path support");
11b6d6450   Igor Mammedov   [CIFS] Only conve...
2680
  			}
8af189715   Steve French   [CIFS] on reconne...
2681
  		}
50c2f7538   Steve French   [CIFS] whitespace...
2682

6848b7334   Steve French   [CIFS] When manda...
2683
2684
  		if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)
  			cERROR(1, "per-share encryption not supported yet");
8af189715   Steve French   [CIFS] on reconne...
2685
  		cap &= CIFS_UNIX_CAP_MASK;
75865f8cc   Steve French   [CIFS] Add in som...
2686
  		if (vol_info && vol_info->no_psx_acl)
8af189715   Steve French   [CIFS] on reconne...
2687
  			cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
75865f8cc   Steve French   [CIFS] Add in som...
2688
  		else if (CIFS_UNIX_POSIX_ACL_CAP & cap) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
2689
  			cFYI(1, "negotiated posix acl support");
2c6292ae4   Al Viro   cifs: don't pass ...
2690
2691
2692
  			if (cifs_sb)
  				cifs_sb->mnt_cifs_flags |=
  					CIFS_MOUNT_POSIXACL;
8af189715   Steve French   [CIFS] on reconne...
2693
  		}
75865f8cc   Steve French   [CIFS] Add in som...
2694
  		if (vol_info && vol_info->posix_paths == 0)
8af189715   Steve French   [CIFS] on reconne...
2695
  			cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
75865f8cc   Steve French   [CIFS] Add in som...
2696
  		else if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
2697
  			cFYI(1, "negotiate posix pathnames");
2c6292ae4   Al Viro   cifs: don't pass ...
2698
2699
  			if (cifs_sb)
  				cifs_sb->mnt_cifs_flags |=
8af189715   Steve French   [CIFS] on reconne...
2700
2701
  					CIFS_MOUNT_POSIX_PATHS;
  		}
50c2f7538   Steve French   [CIFS] whitespace...
2702

b6b38f704   Joe Perches   [CIFS] Neaten cER...
2703
  		cFYI(1, "Negotiate caps 0x%x", (int)cap);
8af189715   Steve French   [CIFS] on reconne...
2704
  #ifdef CONFIG_CIFS_DEBUG2
75865f8cc   Steve French   [CIFS] Add in som...
2705
  		if (cap & CIFS_UNIX_FCNTL_CAP)
b6b38f704   Joe Perches   [CIFS] Neaten cER...
2706
  			cFYI(1, "FCNTL cap");
75865f8cc   Steve French   [CIFS] Add in som...
2707
  		if (cap & CIFS_UNIX_EXTATTR_CAP)
b6b38f704   Joe Perches   [CIFS] Neaten cER...
2708
  			cFYI(1, "EXTATTR cap");
75865f8cc   Steve French   [CIFS] Add in som...
2709
  		if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
b6b38f704   Joe Perches   [CIFS] Neaten cER...
2710
  			cFYI(1, "POSIX path cap");
75865f8cc   Steve French   [CIFS] Add in som...
2711
  		if (cap & CIFS_UNIX_XATTR_CAP)
b6b38f704   Joe Perches   [CIFS] Neaten cER...
2712
  			cFYI(1, "XATTR cap");
75865f8cc   Steve French   [CIFS] Add in som...
2713
  		if (cap & CIFS_UNIX_POSIX_ACL_CAP)
b6b38f704   Joe Perches   [CIFS] Neaten cER...
2714
  			cFYI(1, "POSIX ACL cap");
75865f8cc   Steve French   [CIFS] Add in som...
2715
  		if (cap & CIFS_UNIX_LARGE_READ_CAP)
b6b38f704   Joe Perches   [CIFS] Neaten cER...
2716
  			cFYI(1, "very large read cap");
75865f8cc   Steve French   [CIFS] Add in som...
2717
  		if (cap & CIFS_UNIX_LARGE_WRITE_CAP)
b6b38f704   Joe Perches   [CIFS] Neaten cER...
2718
  			cFYI(1, "very large write cap");
6848b7334   Steve French   [CIFS] When manda...
2719
2720
2721
2722
  		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...
2723
2724
  #endif /* CIFS_DEBUG2 */
  		if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) {
442aa310f   Steve French   [CIFS] Support fo...
2725
  			if (vol_info == NULL) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
2726
  				cFYI(1, "resetting capabilities failed");
442aa310f   Steve French   [CIFS] Support fo...
2727
  			} else
b6b38f704   Joe Perches   [CIFS] Neaten cER...
2728
  				cERROR(1, "Negotiating Unix capabilities "
5a44b3190   Steve French   [CIFS] Add warnin...
2729
2730
2731
2732
2733
  					   "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...
2734
  					   "option.");
5a44b3190   Steve French   [CIFS] Add warnin...
2735

8af189715   Steve French   [CIFS] on reconne...
2736
2737
2738
  		}
  	}
  }
724d9f1cf   Pavel Shilovsky   CIFS: Simplify mo...
2739
2740
  void cifs_setup_cifs_sb(struct smb_vol *pvolume_info,
  			struct cifs_sb_info *cifs_sb)
b1c8d2b42   Jeff Layton   cifs: handle the ...
2741
  {
2de970ff6   Jeff Layton   cifs: implement r...
2742
  	INIT_DELAYED_WORK(&cifs_sb->prune_tlinks, cifs_prune_tlinks);
2ced6f693   Al Viro   cifs: initialize ...
2743
2744
  	spin_lock_init(&cifs_sb->tlink_tree_lock);
  	cifs_sb->tlink_tree = RB_ROOT;
25c7f41e9   Pavel Shilovsky   CIFS: Migrate to ...
2745
  	/*
5eba8ab36   Jeff Layton   cifs: allow for l...
2746
2747
  	 * Temporarily set r/wsize for matching superblock. If we end up using
  	 * new sb then client will later negotiate it downward if needed.
25c7f41e9   Pavel Shilovsky   CIFS: Migrate to ...
2748
  	 */
5eba8ab36   Jeff Layton   cifs: allow for l...
2749
  	cifs_sb->rsize = pvolume_info->rsize;
25c7f41e9   Pavel Shilovsky   CIFS: Migrate to ...
2750
  	cifs_sb->wsize = pvolume_info->wsize;
3b7952109   Steve French   [CIFS] Fix cifs r...
2751
2752
  	cifs_sb->mnt_uid = pvolume_info->linux_uid;
  	cifs_sb->mnt_gid = pvolume_info->linux_gid;
3d3ea8e64   Shirish Pargaonkar   cifs: Add mount o...
2753
2754
2755
2756
  	if (pvolume_info->backupuid_specified)
  		cifs_sb->mnt_backupuid = pvolume_info->backupuid;
  	if (pvolume_info->backupgid_specified)
  		cifs_sb->mnt_backupgid = pvolume_info->backupgid;
3b7952109   Steve French   [CIFS] Fix cifs r...
2757
2758
  	cifs_sb->mnt_file_mode = pvolume_info->file_mode;
  	cifs_sb->mnt_dir_mode = pvolume_info->dir_mode;
5206efd62   Al Viro   cifs: propagate u...
2759
  	cFYI(1, "file mode: 0x%hx  dir mode: 0x%hx",
b6b38f704   Joe Perches   [CIFS] Neaten cER...
2760
  		cifs_sb->mnt_file_mode, cifs_sb->mnt_dir_mode);
3b7952109   Steve French   [CIFS] Fix cifs r...
2761

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

3b7952109   Steve French   [CIFS] Fix cifs r...
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
  	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...
2779
  	if (pvolume_info->nostrictsync)
4717bed68   Steve French   [CIFS] fix build ...
2780
  		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOSSYNC;
13a6e42af   Steve French   [CIFS] add mount ...
2781
2782
  	if (pvolume_info->mand_lock)
  		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOPOSIXBRL;
d4ffff1fa   Pavel Shilovsky   CIFS: Add rwpidfo...
2783
2784
  	if (pvolume_info->rwpidforward)
  		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_RWPIDFORWARD;
3b7952109   Steve French   [CIFS] Fix cifs r...
2785
2786
  	if (pvolume_info->cifs_acl)
  		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL;
3d3ea8e64   Shirish Pargaonkar   cifs: Add mount o...
2787
2788
2789
2790
  	if (pvolume_info->backupuid_specified)
  		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPUID;
  	if (pvolume_info->backupgid_specified)
  		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPGID;
3b7952109   Steve French   [CIFS] Fix cifs r...
2791
2792
2793
2794
2795
2796
  	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...
2797
2798
  	if (pvolume_info->fsc)
  		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_FSCACHE;
0eb8a132c   Jeff Layton   cifs: add "multiu...
2799
2800
2801
  	if (pvolume_info->multiuser)
  		cifs_sb->mnt_cifs_flags |= (CIFS_MOUNT_MULTIUSER |
  					    CIFS_MOUNT_NO_PERM);
d39454ffe   Pavel Shilovsky   CIFS: Add strictc...
2802
2803
  	if (pvolume_info->strict_io)
  		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_STRICT_IO;
3b7952109   Steve French   [CIFS] Fix cifs r...
2804
  	if (pvolume_info->direct_io) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
2805
  		cFYI(1, "mounting share using direct i/o");
3b7952109   Steve French   [CIFS] Fix cifs r...
2806
2807
  		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
  	}
736a33205   Stefan Metzmacher   cifs: add "mfsyml...
2808
2809
2810
2811
2812
2813
2814
2815
  	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...
2816
2817
  
  	if ((pvolume_info->cifs_acl) && (pvolume_info->dynperm))
b6b38f704   Joe Perches   [CIFS] Neaten cER...
2818
2819
  		cERROR(1, "mount option dynperm ignored if cifsacl "
  			   "mount option supported");
b1c8d2b42   Jeff Layton   cifs: handle the ...
2820
  }
f7910cbd9   Jeff Layton   cifs: clean up ws...
2821
  /*
5eba8ab36   Jeff Layton   cifs: allow for l...
2822
2823
2824
   * When the server supports very large reads and writes via POSIX extensions,
   * we can allow up to 2^24-1, minus the size of a READ/WRITE_AND_X header, not
   * including the RFC1001 length.
f7910cbd9   Jeff Layton   cifs: clean up ws...
2825
2826
   *
   * Note that this might make for "interesting" allocation problems during
1190f6a06   Jeff Layton   cifs: fix wsize n...
2827
2828
   * 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.
5eba8ab36   Jeff Layton   cifs: allow for l...
2829
2830
2831
2832
   *
   * For reads, there is a similar problem as we need to allocate an array
   * of kvecs to handle the receive, though that should only need to be done
   * once.
f7910cbd9   Jeff Layton   cifs: clean up ws...
2833
   */
1190f6a06   Jeff Layton   cifs: fix wsize n...
2834
  #define CIFS_MAX_WSIZE ((1<<24) - 1 - sizeof(WRITE_REQ) + 4)
5eba8ab36   Jeff Layton   cifs: allow for l...
2835
  #define CIFS_MAX_RSIZE ((1<<24) - sizeof(READ_RSP) + 4)
f7910cbd9   Jeff Layton   cifs: clean up ws...
2836
2837
  
  /*
5eba8ab36   Jeff Layton   cifs: allow for l...
2838
2839
2840
   * When the server doesn't allow large posix writes, only allow a rsize/wsize
   * of 2^17-1 minus the size of the call header. That allows for a read or
   * write up to the maximum size described by RFC1002.
f7910cbd9   Jeff Layton   cifs: clean up ws...
2841
   */
94443f434   Pavel Shilovsky   CIFS: Fix incorre...
2842
  #define CIFS_MAX_RFC1002_WSIZE ((1<<17) - 1 - sizeof(WRITE_REQ) + 4)
5eba8ab36   Jeff Layton   cifs: allow for l...
2843
  #define CIFS_MAX_RFC1002_RSIZE ((1<<17) - 1 - sizeof(READ_RSP) + 4)
f7910cbd9   Jeff Layton   cifs: clean up ws...
2844
2845
2846
2847
2848
2849
  
  /*
   * 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.
   */
5eba8ab36   Jeff Layton   cifs: allow for l...
2850
2851
2852
2853
2854
2855
2856
  #define CIFS_DEFAULT_IOSIZE (1024 * 1024)
  
  /*
   * Windows only supports a max of 60k reads. Default to that when posix
   * extensions aren't in force.
   */
  #define CIFS_DEFAULT_NON_POSIX_RSIZE (60 * 1024)
f7910cbd9   Jeff Layton   cifs: clean up ws...
2857
2858
  
  static unsigned int
96daf2b09   Steve French   [CIFS] Rename thr...
2859
  cifs_negotiate_wsize(struct cifs_tcon *tcon, struct smb_vol *pvolume_info)
f7910cbd9   Jeff Layton   cifs: clean up ws...
2860
2861
2862
2863
  {
  	__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 :
5eba8ab36   Jeff Layton   cifs: allow for l...
2864
  				CIFS_DEFAULT_IOSIZE;
f7910cbd9   Jeff Layton   cifs: clean up ws...
2865
2866
2867
  
  	/* 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...
2868
  		wsize = min_t(unsigned int, wsize, CIFS_MAX_RFC1002_WSIZE);
f7910cbd9   Jeff Layton   cifs: clean up ws...
2869

1190f6a06   Jeff Layton   cifs: fix wsize n...
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
  	/*
  	 * 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...
2880
2881
2882
2883
2884
2885
  
  	/* hard limit of CIFS_MAX_WSIZE */
  	wsize = min_t(unsigned int, wsize, CIFS_MAX_WSIZE);
  
  	return wsize;
  }
5eba8ab36   Jeff Layton   cifs: allow for l...
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
  static unsigned int
  cifs_negotiate_rsize(struct cifs_tcon *tcon, struct smb_vol *pvolume_info)
  {
  	__u64 unix_cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
  	struct TCP_Server_Info *server = tcon->ses->server;
  	unsigned int rsize, defsize;
  
  	/*
  	 * Set default value...
  	 *
  	 * HACK alert! Ancient servers have very small buffers. Even though
  	 * MS-CIFS indicates that servers are only limited by the client's
  	 * bufsize for reads, testing against win98se shows that it throws
  	 * INVALID_PARAMETER errors if you try to request too large a read.
  	 *
  	 * If the server advertises a MaxBufferSize of less than one page,
  	 * assume that it also can't satisfy reads larger than that either.
  	 *
  	 * FIXME: Is there a better heuristic for this?
  	 */
  	if (tcon->unix_ext && (unix_cap & CIFS_UNIX_LARGE_READ_CAP))
  		defsize = CIFS_DEFAULT_IOSIZE;
  	else if (server->capabilities & CAP_LARGE_READ_X)
  		defsize = CIFS_DEFAULT_NON_POSIX_RSIZE;
  	else if (server->maxBuf >= PAGE_CACHE_SIZE)
  		defsize = CIFSMaxBufSize;
  	else
  		defsize = server->maxBuf - sizeof(READ_RSP);
  
  	rsize = pvolume_info->rsize ? pvolume_info->rsize : defsize;
  
  	/*
  	 * no CAP_LARGE_READ_X? Then MS-CIFS states that we must limit this to
  	 * the client's MaxBufferSize.
  	 */
  	if (!(server->capabilities & CAP_LARGE_READ_X))
  		rsize = min_t(unsigned int, CIFSMaxBufSize, rsize);
  
  	/* hard limit of CIFS_MAX_RSIZE */
  	rsize = min_t(unsigned int, rsize, CIFS_MAX_RSIZE);
  
  	return rsize;
  }
e4cce94c9   Igor Mammedov   [CIFS] Prevent OO...
2929
  static int
96daf2b09   Steve French   [CIFS] Rename thr...
2930
  is_path_accessible(int xid, struct cifs_tcon *tcon,
e4cce94c9   Igor Mammedov   [CIFS] Prevent OO...
2931
2932
2933
  		   struct cifs_sb_info *cifs_sb, const char *full_path)
  {
  	int rc;
e4cce94c9   Igor Mammedov   [CIFS] Prevent OO...
2934
  	FILE_ALL_INFO *pfile_info;
e4cce94c9   Igor Mammedov   [CIFS] Prevent OO...
2935
2936
2937
2938
2939
2940
2941
2942
  	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...
2943
2944
2945
2946
2947
  
  	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...
2948
2949
2950
  	kfree(pfile_info);
  	return rc;
  }
b9bce2e9f   Jeff Layton   cifs: fix expand_...
2951
2952
  static void
  cleanup_volume_info_contents(struct smb_vol *volume_info)
1bfe73c25   Igor Mammedov   Remote DFS root s...
2953
  {
b946845a9   Sean Finney   cifs: cifs_parse_...
2954
  	kfree(volume_info->username);
1bfe73c25   Igor Mammedov   Remote DFS root s...
2955
  	kzfree(volume_info->password);
13589c437   Steve French   [CIFS] possible m...
2956
2957
  	if (volume_info->UNCip != volume_info->UNC + 2)
  		kfree(volume_info->UNCip);
95c754545   Jesper Juhl   CIFS: Don't free ...
2958
  	kfree(volume_info->UNC);
b946845a9   Sean Finney   cifs: cifs_parse_...
2959
2960
  	kfree(volume_info->domainname);
  	kfree(volume_info->iocharset);
1bfe73c25   Igor Mammedov   Remote DFS root s...
2961
  	kfree(volume_info->prepath);
b9bce2e9f   Jeff Layton   cifs: fix expand_...
2962
2963
2964
2965
2966
2967
2968
2969
  }
  
  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...
2970
  	kfree(volume_info);
1bfe73c25   Igor Mammedov   Remote DFS root s...
2971
  }
b9bce2e9f   Jeff Layton   cifs: fix expand_...
2972

2d6d589d8   Steve French   [CIFS] remove som...
2973
  #ifdef CONFIG_CIFS_DFS_UPCALL
1bfe73c25   Igor Mammedov   Remote DFS root s...
2974
2975
2976
  /* 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...
2977
  build_unc_path_to_root(const struct smb_vol *vol,
1bfe73c25   Igor Mammedov   Remote DFS root s...
2978
2979
  		const struct cifs_sb_info *cifs_sb)
  {
b2a0fa152   Jeff Layton   cifs: fix build_u...
2980
2981
2982
  	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...
2983

b2a0fa152   Jeff Layton   cifs: fix build_u...
2984
  	full_path = kmalloc(unc_len + pplen + 1, GFP_KERNEL);
1bfe73c25   Igor Mammedov   Remote DFS root s...
2985
2986
  	if (full_path == NULL)
  		return ERR_PTR(-ENOMEM);
b2a0fa152   Jeff Layton   cifs: fix build_u...
2987
2988
2989
2990
2991
2992
2993
2994
2995
  	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...
2996
  	convert_delimiter(full_path, CIFS_DIR_SEP(cifs_sb));
b2a0fa152   Jeff Layton   cifs: fix build_u...
2997
  	cFYI(1, "%s: full_path=%s", __func__, full_path);
1bfe73c25   Igor Mammedov   Remote DFS root s...
2998
2999
  	return full_path;
  }
dd6139458   Sean Finney   cifs: Extract DFS...
3000
3001
3002
3003
  
  /*
   * Perform a dfs referral query for a share and (optionally) prefix
   *
046462abc   Sean Finney   cifs: Simplify ha...
3004
3005
3006
   * 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...
3007
3008
3009
3010
3011
   *
   * 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...
3012
  expand_dfs_referral(int xid, struct cifs_ses *pSesInfo,
dd6139458   Sean Finney   cifs: Extract DFS...
3013
  		    struct smb_vol *volume_info, struct cifs_sb_info *cifs_sb,
046462abc   Sean Finney   cifs: Simplify ha...
3014
  		    int check_prefix)
dd6139458   Sean Finney   cifs: Extract DFS...
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
  {
  	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...
3040

dd6139458   Sean Finney   cifs: Extract DFS...
3041
3042
3043
  		if (IS_ERR(mdata)) {
  			rc = PTR_ERR(mdata);
  			mdata = NULL;
b9bce2e9f   Jeff Layton   cifs: fix expand_...
3044
3045
3046
3047
3048
  		} 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...
3049
  		}
b9bce2e9f   Jeff Layton   cifs: fix expand_...
3050
3051
  		kfree(fake_devname);
  		kfree(cifs_sb->mountdata);
046462abc   Sean Finney   cifs: Simplify ha...
3052
  		cifs_sb->mountdata = mdata;
dd6139458   Sean Finney   cifs: Extract DFS...
3053
3054
3055
3056
  	}
  	kfree(full_path);
  	return rc;
  }
2d6d589d8   Steve French   [CIFS] remove som...
3057
  #endif
1bfe73c25   Igor Mammedov   Remote DFS root s...
3058

04db79b01   Jeff Layton   cifs: factor smb_...
3059
3060
3061
  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
3062
  {
724d9f1cf   Pavel Shilovsky   CIFS: Simplify mo...
3063
  	int rc = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3064

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

7586b7658   Jeff Layton   cifs: don't decla...
3068
  	if (volume_info->nullauth) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
3069
  		cFYI(1, "null user");
446b23a75   Pavel Shilovsky   CIFS: Fix problem...
3070
  		volume_info->username = kzalloc(1, GFP_KERNEL);
04db79b01   Jeff Layton   cifs: factor smb_...
3071
3072
  		if (volume_info->username == NULL)
  			return -ENOMEM;
7586b7658   Jeff Layton   cifs: don't decla...
3073
  	} else if (volume_info->username) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3074
  		/* BB fixme parse for domain name here */
b6b38f704   Joe Perches   [CIFS] Neaten cER...
3075
  		cFYI(1, "Username: %s", volume_info->username);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3076
  	} else {
bf8206791   Steve French   [CIFS] Kerberos a...
3077
  		cifserror("No username specified");
50c2f7538   Steve French   [CIFS] whitespace...
3078
3079
  	/* 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_...
3080
  		return -EINVAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3081
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3082
  	/* this is needed for ASCII cp to Unicode converts */
7586b7658   Jeff Layton   cifs: don't decla...
3083
  	if (volume_info->iocharset == NULL) {
a5fc4ce01   Jeff Layton   cifs: track local...
3084
3085
  		/* load_nls_default cannot return null */
  		volume_info->local_nls = load_nls_default();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3086
  	} else {
a5fc4ce01   Jeff Layton   cifs: track local...
3087
3088
  		volume_info->local_nls = load_nls(volume_info->iocharset);
  		if (volume_info->local_nls == NULL) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
3089
3090
  			cERROR(1, "CIFS mount error: iocharset %s not found",
  				 volume_info->iocharset);
04db79b01   Jeff Layton   cifs: factor smb_...
3091
  			return -ELIBACC;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3092
3093
  		}
  	}
724d9f1cf   Pavel Shilovsky   CIFS: Simplify mo...
3094

724d9f1cf   Pavel Shilovsky   CIFS: Simplify mo...
3095
3096
  	return rc;
  }
04db79b01   Jeff Layton   cifs: factor smb_...
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
  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;
  }
66bfaadc3   Jeff Layton   cifs: tune bdi.ra...
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
  /* make sure ra_pages is a multiple of rsize */
  static inline unsigned int
  cifs_ra_pages(struct cifs_sb_info *cifs_sb)
  {
  	unsigned int reads;
  	unsigned int rsize_pages = cifs_sb->rsize / PAGE_CACHE_SIZE;
  
  	if (rsize_pages >= default_backing_dev_info.ra_pages)
  		return default_backing_dev_info.ra_pages;
  	else if (rsize_pages == 0)
  		return rsize_pages;
  
  	reads = default_backing_dev_info.ra_pages / rsize_pages;
  	return reads * rsize_pages;
  }
724d9f1cf   Pavel Shilovsky   CIFS: Simplify mo...
3130
  int
2c6292ae4   Al Viro   cifs: don't pass ...
3131
  cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *volume_info)
724d9f1cf   Pavel Shilovsky   CIFS: Simplify mo...
3132
3133
3134
  {
  	int rc = 0;
  	int xid;
96daf2b09   Steve French   [CIFS] Rename thr...
3135
3136
  	struct cifs_ses *pSesInfo;
  	struct cifs_tcon *tcon;
724d9f1cf   Pavel Shilovsky   CIFS: Simplify mo...
3137
3138
3139
3140
3141
  	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...
3142
  #endif
dd8544661   Al Viro   take bdi setup/de...
3143
3144
3145
3146
  
  	rc = bdi_setup_and_register(&cifs_sb->bdi, "cifs", BDI_CAP_MAP_COPY);
  	if (rc)
  		return rc;
20547490c   Jeff Layton   cifs: move bdi_se...
3147
  #ifdef CONFIG_CIFS_DFS_UPCALL
724d9f1cf   Pavel Shilovsky   CIFS: Simplify mo...
3148
3149
3150
3151
3152
3153
3154
  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...
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
  		FreeXid(xid);
  	}
  #endif
  	tcon = NULL;
  	pSesInfo = NULL;
  	srvTcp = NULL;
  	full_path = NULL;
  	tlink = NULL;
  
  	xid = GetXid();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3165

63c038c29   Jeff Layton   cifs: move alloca...
3166
  	/* get a reference to a tcp session */
7586b7658   Jeff Layton   cifs: don't decla...
3167
  	srvTcp = cifs_get_tcp_session(volume_info);
63c038c29   Jeff Layton   cifs: move alloca...
3168
3169
  	if (IS_ERR(srvTcp)) {
  		rc = PTR_ERR(srvTcp);
dd8544661   Al Viro   take bdi setup/de...
3170
  		bdi_destroy(&cifs_sb->bdi);
63c038c29   Jeff Layton   cifs: move alloca...
3171
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3172
  	}
36988c76f   Jeff Layton   cifs: move SMB se...
3173
3174
3175
3176
3177
3178
  	/* 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
3179
  	}
50c2f7538   Steve French   [CIFS] whitespace...
3180

d00c28de5   Jeff Layton   cifs: move tcon f...
3181
3182
3183
3184
3185
  	/* 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...
3186
  		goto remote_path_check;
d00c28de5   Jeff Layton   cifs: move tcon f...
3187
  	}
1bfe73c25   Igor Mammedov   Remote DFS root s...
3188

d82c2df54   Steve French   [CIFS] minor clea...
3189
  	/* tell server which Unix caps we support */
6848b7334   Steve French   [CIFS] When manda...
3190
  	if (tcon->ses->capabilities & CAP_UNIX) {
d82c2df54   Steve French   [CIFS] minor clea...
3191
3192
  		/* reset of caps checks mount to see if unix extensions
  		   disabled for just this mount */
2c6292ae4   Al Viro   cifs: don't pass ...
3193
  		reset_cifs_unix_caps(xid, tcon, cifs_sb, volume_info);
6848b7334   Steve French   [CIFS] When manda...
3194
3195
3196
3197
3198
3199
3200
  		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...
3201
  		tcon->unix_ext = 0; /* server does not support them */
c18c842b1   Steve French   [CIFS] Allow disa...
3202

6848b7334   Steve French   [CIFS] When manda...
3203
3204
3205
3206
3207
  	/* do not care if following two calls succeed - informational */
  	if (!tcon->ipc) {
  		CIFSSMBQFSDeviceInfo(xid, tcon);
  		CIFSSMBQFSAttributeInfo(xid, tcon);
  	}
f7910cbd9   Jeff Layton   cifs: clean up ws...
3208
  	cifs_sb->wsize = cifs_negotiate_wsize(tcon, volume_info);
5eba8ab36   Jeff Layton   cifs: allow for l...
3209
  	cifs_sb->rsize = cifs_negotiate_rsize(tcon, volume_info);
f7910cbd9   Jeff Layton   cifs: clean up ws...
3210

66bfaadc3   Jeff Layton   cifs: tune bdi.ra...
3211
3212
  	/* tune readahead according to rsize */
  	cifs_sb->bdi.ra_pages = cifs_ra_pages(cifs_sb);
f7910cbd9   Jeff Layton   cifs: clean up ws...
3213

1bfe73c25   Igor Mammedov   Remote DFS root s...
3214
  remote_path_check:
c1508ca23   Sean Finney   cifs: Add support...
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
  #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...
3225
  						cifs_sb, false);
c1508ca23   Sean Finney   cifs: Add support...
3226
3227
3228
3229
3230
3231
  		if (!refrc) {
  			referral_walks_count++;
  			goto try_mount_again;
  		}
  	}
  #endif
f87d39d95   Steve French   [CIFS] Migrate fr...
3232
  	/* check if a whole path is not remote */
709456437   Jeff Layton   cifs: always do i...
3233
  	if (!rc && tcon) {
e4cce94c9   Igor Mammedov   [CIFS] Prevent OO...
3234
  		/* build_path_to_root works only when we have a valid tcon */
f87d39d95   Steve French   [CIFS] Migrate fr...
3235
  		full_path = cifs_build_path_to_root(volume_info, cifs_sb, tcon);
e4cce94c9   Igor Mammedov   [CIFS] Prevent OO...
3236
3237
3238
3239
3240
  		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...
3241
  		if (rc != 0 && rc != -EREMOTE) {
e4cce94c9   Igor Mammedov   [CIFS] Prevent OO...
3242
3243
3244
3245
3246
  			kfree(full_path);
  			goto mount_fail_check;
  		}
  		kfree(full_path);
  	}
1bfe73c25   Igor Mammedov   Remote DFS root s...
3247
3248
  	/* get referral if needed */
  	if (rc == -EREMOTE) {
d036f50fc   Steve French   [CIFS] Fix build ...
3249
  #ifdef CONFIG_CIFS_DFS_UPCALL
5c2503a8e   Igor Mammedov   Added loop check ...
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
  		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...
3260

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

dd6139458   Sean Finney   cifs: Extract DFS...
3264
  		if (!rc) {
5c2503a8e   Igor Mammedov   Added loop check ...
3265
  			referral_walks_count++;
1bfe73c25   Igor Mammedov   Remote DFS root s...
3266
3267
  			goto try_mount_again;
  		}
dd6139458   Sean Finney   cifs: Extract DFS...
3268
  		goto mount_fail_check;
d036f50fc   Steve French   [CIFS] Fix build ...
3269
3270
3271
  #else /* No DFS support, return error on mount */
  		rc = -EOPNOTSUPP;
  #endif
1bfe73c25   Igor Mammedov   Remote DFS root s...
3272
  	}
9d002df49   Jeff Layton   cifs: add routine...
3273
3274
3275
3276
3277
3278
3279
3280
3281
  	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...
3282
  	tlink->tl_uid = pSesInfo->linux_uid;
9d002df49   Jeff Layton   cifs: add routine...
3283
3284
3285
3286
  	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...
3287
  	cifs_sb->master_tlink = tlink;
9d002df49   Jeff Layton   cifs: add routine...
3288
  	spin_lock(&cifs_sb->tlink_tree_lock);
b647c35f7   Jeff Layton   cifs: convert tli...
3289
  	tlink_rb_insert(&cifs_sb->tlink_tree, tlink);
9d002df49   Jeff Layton   cifs: add routine...
3290
  	spin_unlock(&cifs_sb->tlink_tree_lock);
413e661c1   Jeff Layton   cifs: store point...
3291

2de970ff6   Jeff Layton   cifs: implement r...
3292
3293
  	queue_delayed_work(system_nrt_wq, &cifs_sb->prune_tlinks,
  				TLINK_IDLE_EXPIRE);
1bfe73c25   Igor Mammedov   Remote DFS root s...
3294
3295
3296
  mount_fail_check:
  	/* on error free sesinfo and tcon struct if needed */
  	if (rc) {
1bfe73c25   Igor Mammedov   Remote DFS root s...
3297
  		/* If find_unc succeeded then rc == 0 so we can not end */
25985edce   Lucas De Marchi   Fix common misspe...
3298
  		/* up accidentally freeing someone elses tcon struct */
1bfe73c25   Igor Mammedov   Remote DFS root s...
3299
3300
3301
3302
3303
3304
  		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...
3305
  		bdi_destroy(&cifs_sb->bdi);
1bfe73c25   Igor Mammedov   Remote DFS root s...
3306
  	}
70fe7dc05   Jeff Layton   [CIFS] clean up e...
3307
  out:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3308
3309
3310
  	FreeXid(xid);
  	return rc;
  }
8d1bca328   Jeff Layton   cifs: correctly h...
3311
3312
3313
3314
  /*
   * 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
3315
  int
96daf2b09   Steve French   [CIFS] Rename thr...
3316
3317
  CIFSTCon(unsigned int xid, struct cifs_ses *ses,
  	 const char *tree, struct cifs_tcon *tcon,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3318
3319
3320
3321
3322
3323
3324
3325
  	 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...
3326
3327
  	int length;
  	__u16 bytes_left, count;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3328
3329
3330
3331
3332
  
  	if (ses == NULL)
  		return -EIO;
  
  	smb_buffer = cifs_buf_get();
ca43e3bee   Steve French   [CIFS] Fix checkp...
3333
  	if (smb_buffer == NULL)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3334
  		return -ENOMEM;
ca43e3bee   Steve French   [CIFS] Fix checkp...
3335

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3336
3337
3338
3339
  	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...
3340
3341
  
  	smb_buffer->Mid = GetNextMid(ses->server);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3342
3343
3344
3345
3346
3347
  	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
3348
  	bcc_ptr = &pSMB->Password[0];
8d1bca328   Jeff Layton   cifs: correctly h...
3349
  	if (!tcon || (ses->server->sec_mode & SECMODE_USER)) {
eeac8047f   Steve French   [CIFS] Fix CIFS t...
3350
  		pSMB->PasswordLength = cpu_to_le16(1);	/* minimum */
7c7b25bc8   Steve French   [CIFS] Support fo...
3351
  		*bcc_ptr = 0; /* password is null byte */
eeac8047f   Steve French   [CIFS] Fix CIFS t...
3352
  		bcc_ptr++;              /* skip password */
7c7b25bc8   Steve French   [CIFS] Support fo...
3353
  		/* already aligned so no need to do it below */
eeac8047f   Steve French   [CIFS] Fix CIFS t...
3354
  	} else {
540b2e377   Shirish Pargaonkar   cifs: Fix regress...
3355
  		pSMB->PasswordLength = cpu_to_le16(CIFS_AUTH_RESP_SIZE);
eeac8047f   Steve French   [CIFS] Fix CIFS t...
3356
3357
3358
  		/* 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...
3359
  		   weaker LANMAN (which we do not send by default) is accepted
eeac8047f   Steve French   [CIFS] Fix CIFS t...
3360
3361
  		   by Samba (not sure whether other servers allow
  		   NTLMv2 password here) */
7c7b25bc8   Steve French   [CIFS] Support fo...
3362
  #ifdef CONFIG_CIFS_WEAK_PW_HASH
04912d6a2   Jeff Layton   cifs: rename "ext...
3363
  		if ((global_secflags & CIFSSEC_MAY_LANMAN) &&
00e485b01   Jeff Layton   cifs: store passw...
3364
  		    (ses->server->secType == LANMAN))
d3ba50b17   Shirish Pargaonkar   NTLM auth and sig...
3365
  			calc_lanman_hash(tcon->password, ses->server->cryptkey,
96daf2b09   Steve French   [CIFS] Rename thr...
3366
  					 ses->server->sec_mode &
4e53a3fb9   Jeff Layton   cifs: have calc_l...
3367
3368
  					    SECMODE_PW_ENCRYPT ? true : false,
  					 bcc_ptr);
7c7b25bc8   Steve French   [CIFS] Support fo...
3369
3370
  		else
  #endif /* CIFS_WEAK_PW_HASH */
ee2c92585   Shirish Pargaonkar   cifs: More crypto...
3371
  		rc = SMBNTencrypt(tcon->password, ses->server->cryptkey,
9ef5992e4   Shirish Pargaonkar   cifs: Assume pass...
3372
  					bcc_ptr, nls_codepage);
eeac8047f   Steve French   [CIFS] Fix CIFS t...
3373

540b2e377   Shirish Pargaonkar   cifs: Fix regress...
3374
  		bcc_ptr += CIFS_AUTH_RESP_SIZE;
fb8c4b14d   Steve French   [CIFS] whitespace...
3375
  		if (ses->capabilities & CAP_UNICODE) {
7c7b25bc8   Steve French   [CIFS] Support fo...
3376
3377
3378
3379
  			/* must align unicode strings */
  			*bcc_ptr = 0; /* null byte password */
  			bcc_ptr++;
  		}
eeac8047f   Steve French   [CIFS] Fix CIFS t...
3380
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3381

96daf2b09   Steve French   [CIFS] Rename thr...
3382
  	if (ses->server->sec_mode &
a878fb221   Steve French   [CIFS] Do not lim...
3383
  			(SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
  		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...
3395
3396
  		    cifs_strtoUCS((__le16 *) bcc_ptr, tree,
  			6 /* max utf8 char length in bytes */ *
a878fb221   Steve French   [CIFS] Do not lim...
3397
3398
  			(/* 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
3399
3400
  		bcc_ptr += 2;	/* skip trailing null */
  	} else {		/* ASCII */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3401
3402
3403
3404
3405
3406
3407
  		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 ...
3408
3409
  	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
3410
  	pSMB->ByteCount = cpu_to_le16(count);
133672efb   Steve French   [CIFS] Fix buffer...
3411
  	rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length,
7749981ec   Jeff Layton   cifs: remove code...
3412
  			 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3413

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3414
3415
  	/* above now done in SendReceive */
  	if ((rc == 0) && (tcon != NULL)) {
0e0d2cf32   Steve French   [CIFS] Remove spa...
3416
  		bool is_unicode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3417
  		tcon->tidStatus = CifsGood;
3b7952109   Steve French   [CIFS] Fix cifs r...
3418
  		tcon->need_reconnect = false;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3419
3420
  		tcon->tid = smb_buffer_response->Tid;
  		bcc_ptr = pByteArea(smb_buffer_response);
690c522fa   Jeff Layton   cifs: use get/put...
3421
  		bytes_left = get_bcc(smb_buffer_response);
cc20c031b   Jeff Layton   cifs: convert CIF...
3422
  		length = strnlen(bcc_ptr, bytes_left - 2);
0e0d2cf32   Steve French   [CIFS] Remove spa...
3423
3424
3425
3426
  		if (smb_buffer->Flags2 & SMBFLG2_UNICODE)
  			is_unicode = true;
  		else
  			is_unicode = false;
cc20c031b   Jeff Layton   cifs: convert CIF...
3427

50c2f7538   Steve French   [CIFS] whitespace...
3428
  		/* skip service field (NB: this field is always ASCII) */
7f8ed420f   Steve French   [CIFS] CIFS suppo...
3429
3430
3431
  		if (length == 3) {
  			if ((bcc_ptr[0] == 'I') && (bcc_ptr[1] == 'P') &&
  			    (bcc_ptr[2] == 'C')) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
3432
  				cFYI(1, "IPC connection");
7f8ed420f   Steve French   [CIFS] CIFS suppo...
3433
3434
3435
3436
3437
  				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...
3438
  				cFYI(1, "disk share connection");
7f8ed420f   Steve French   [CIFS] CIFS suppo...
3439
3440
  			}
  		}
50c2f7538   Steve French   [CIFS] whitespace...
3441
  		bcc_ptr += length + 1;
cc20c031b   Jeff Layton   cifs: convert CIF...
3442
  		bytes_left -= (length + 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3443
  		strncpy(tcon->treeName, tree, MAX_TREE_SIZE);
cc20c031b   Jeff Layton   cifs: convert CIF...
3444
3445
  
  		/* mostly informational -- no need to fail on error here */
90a98b2f3   Jeff Layton   cifs: free native...
3446
  		kfree(tcon->nativeFileSystem);
d185cda77   Steve French   [CIFS] rename cif...
3447
  		tcon->nativeFileSystem = cifs_strndup_from_ucs(bcc_ptr,
0e0d2cf32   Steve French   [CIFS] Remove spa...
3448
  						      bytes_left, is_unicode,
cc20c031b   Jeff Layton   cifs: convert CIF...
3449
  						      nls_codepage);
b6b38f704   Joe Perches   [CIFS] Neaten cER...
3450
  		cFYI(1, "nativeFileSystem=%s", tcon->nativeFileSystem);
cc20c031b   Jeff Layton   cifs: convert CIF...
3451

fb8c4b14d   Steve French   [CIFS] whitespace...
3452
  		if ((smb_buffer_response->WordCount == 3) ||
1a4e15a04   Steve French   [CIFS] Missing fl...
3453
3454
  			 (smb_buffer_response->WordCount == 7))
  			/* field is in same location */
3979877e5   Steve French   [CIFS] Support fo...
3455
3456
3457
  			tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
  		else
  			tcon->Flags = 0;
b6b38f704   Joe Perches   [CIFS] Neaten cER...
3458
  		cFYI(1, "Tcon flags: 0x%x ", tcon->Flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3459
  	} else if ((rc == 0) && tcon == NULL) {
50c2f7538   Steve French   [CIFS] whitespace...
3460
  		/* all we need to save for IPC$ connection */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3461
3462
  		ses->ipc_tid = smb_buffer_response->Tid;
  	}
a8a11d399   Mariusz Kozlowski   [CIFS] remove som...
3463
  	cifs_buf_release(smb_buffer);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3464
3465
  	return rc;
  }
2a9b99516   Al Viro   sanitize cifs_umo...
3466
3467
  void
  cifs_umount(struct cifs_sb_info *cifs_sb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3468
  {
b647c35f7   Jeff Layton   cifs: convert tli...
3469
3470
3471
  	struct rb_root *root = &cifs_sb->tlink_tree;
  	struct rb_node *node;
  	struct tcon_link *tlink;
9d002df49   Jeff Layton   cifs: add routine...
3472

2de970ff6   Jeff Layton   cifs: implement r...
3473
  	cancel_delayed_work_sync(&cifs_sb->prune_tlinks);
b647c35f7   Jeff Layton   cifs: convert tli...
3474
3475
3476
3477
3478
3479
  	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
3480

b647c35f7   Jeff Layton   cifs: convert tli...
3481
3482
3483
3484
3485
  		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...
3486

dd8544661   Al Viro   take bdi setup/de...
3487
  	bdi_destroy(&cifs_sb->bdi);
d757d71bf   Al Viro   cifs: pull freein...
3488
3489
3490
  	kfree(cifs_sb->mountdata);
  	unload_nls(cifs_sb->local_nls);
  	kfree(cifs_sb);
50c2f7538   Steve French   [CIFS] whitespace...
3491
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3492

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

198b56827   Jeff Layton   cifs: break negot...
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
  	/* 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
3508
  	}
198b56827   Jeff Layton   cifs: break negot...
3509
3510
  	if (rc == 0) {
  		spin_lock(&GlobalMid_Lock);
7fdbaa1b8   Jeff Layton   cifs: don't allow...
3511
  		if (server->tcpStatus == CifsNeedNegotiate)
198b56827   Jeff Layton   cifs: break negot...
3512
3513
3514
3515
  			server->tcpStatus = CifsGood;
  		else
  			rc = -EHOSTDOWN;
  		spin_unlock(&GlobalMid_Lock);
26b994fad   Steve French   [CIFS] Code clean...
3516

198b56827   Jeff Layton   cifs: break negot...
3517
3518
3519
3520
  	}
  
  	return rc;
  }
96daf2b09   Steve French   [CIFS] Rename thr...
3521
  int cifs_setup_session(unsigned int xid, struct cifs_ses *ses,
198b56827   Jeff Layton   cifs: break negot...
3522
3523
3524
3525
  			struct nls_table *nls_info)
  {
  	int rc = 0;
  	struct TCP_Server_Info *server = ses->server;
26b994fad   Steve French   [CIFS] Code clean...
3526

198b56827   Jeff Layton   cifs: break negot...
3527
3528
  	ses->flags = 0;
  	ses->capabilities = server->capabilities;
26b994fad   Steve French   [CIFS] Code clean...
3529
  	if (linuxExtEnabled == 0)
198b56827   Jeff Layton   cifs: break negot...
3530
  		ses->capabilities &= (~CAP_UNIX);
20418acd6   Steve French   [CIFS] Remove old...
3531

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

198b56827   Jeff Layton   cifs: break negot...
3535
  	rc = CIFS_SessSetup(xid, ses, nls_info);
26b994fad   Steve French   [CIFS] Code clean...
3536
  	if (rc) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
3537
  		cERROR(1, "Send error in SessSetup = %d", rc);
26b994fad   Steve French   [CIFS] Code clean...
3538
  	} else {
5d0d28824   Shirish Pargaonkar   NTLM authenticati...
3539
3540
  		mutex_lock(&ses->server->srv_mutex);
  		if (!server->session_estab) {
21e733930   Shirish Pargaonkar   NTLM auth and sig...
3541
  			server->session_key.response = ses->auth_key.response;
5d0d28824   Shirish Pargaonkar   NTLM authenticati...
3542
  			server->session_key.len = ses->auth_key.len;
21e733930   Shirish Pargaonkar   NTLM auth and sig...
3543
3544
3545
  			server->sequence_number = 0x2;
  			server->session_estab = true;
  			ses->auth_key.response = NULL;
5d0d28824   Shirish Pargaonkar   NTLM authenticati...
3546
3547
  		}
  		mutex_unlock(&server->srv_mutex);
b6b38f704   Joe Perches   [CIFS] Neaten cER...
3548
  		cFYI(1, "CIFS Session Established successfully");
20418acd6   Steve French   [CIFS] Remove old...
3549
  		spin_lock(&GlobalMid_Lock);
198b56827   Jeff Layton   cifs: break negot...
3550
3551
  		ses->status = CifsGood;
  		ses->need_reconnect = false;
20418acd6   Steve French   [CIFS] Remove old...
3552
  		spin_unlock(&GlobalMid_Lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3553
  	}
26b994fad   Steve French   [CIFS] Code clean...
3554

21e733930   Shirish Pargaonkar   NTLM auth and sig...
3555
3556
3557
  	kfree(ses->auth_key.response);
  	ses->auth_key.response = NULL;
  	ses->auth_key.len = 0;
d3686d54c   Shirish Pargaonkar   cifs: Cleanup and...
3558
3559
  	kfree(ses->ntlmssp);
  	ses->ntlmssp = NULL;
21e733930   Shirish Pargaonkar   NTLM auth and sig...
3560

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3561
3562
  	return rc;
  }
96daf2b09   Steve French   [CIFS] Rename thr...
3563
  static struct cifs_tcon *
9d002df49   Jeff Layton   cifs: add routine...
3564
3565
  cifs_construct_tcon(struct cifs_sb_info *cifs_sb, uid_t fsuid)
  {
96daf2b09   Steve French   [CIFS] Rename thr...
3566
3567
3568
  	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...
3569
  	struct smb_vol *vol_info;
34c87901e   Steve French   Shrink stack spac...
3570
3571
3572
  	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...
3573
3574
3575
3576
3577
3578
  
  	vol_info = kzalloc(sizeof(*vol_info), GFP_KERNEL);
  	if (vol_info == NULL) {
  		tcon = ERR_PTR(-ENOMEM);
  		goto out;
  	}
ea1be1a3c   Steve French   [CIFS] update lim...
3579
  	snprintf(username, sizeof(username), "krb50x%x", fsuid);
9d002df49   Jeff Layton   cifs: add routine...
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
  	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...
3594
  	spin_lock(&cifs_tcp_ses_lock);
9d002df49   Jeff Layton   cifs: add routine...
3595
  	++master_tcon->ses->server->srv_count;
3f9bcca78   Suresh Jayaraman   cifs: convert cif...
3596
  	spin_unlock(&cifs_tcp_ses_lock);
9d002df49   Jeff Layton   cifs: add routine...
3597
3598
3599
  
  	ses = cifs_get_smb_ses(master_tcon->ses->server, vol_info);
  	if (IS_ERR(ses)) {
96daf2b09   Steve French   [CIFS] Rename thr...
3600
  		tcon = (struct cifs_tcon *)ses;
9d002df49   Jeff Layton   cifs: add routine...
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
  		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...
3618
  struct cifs_tcon *
9d002df49   Jeff Layton   cifs: add routine...
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
  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...
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
  /* 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...
3670
3671
3672
3673
3674
3675
3676
  /*
   * 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...
3677
   * First, search the rbtree for an existing tcon for this fsuid. If one
9d002df49   Jeff Layton   cifs: add routine...
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
   * 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...
3690
  	uid_t fsuid = current_fsuid();
9d002df49   Jeff Layton   cifs: add routine...
3691
3692
3693
3694
3695
3696
  	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...
3697
  	tlink = tlink_rb_search(&cifs_sb->tlink_tree, fsuid);
9d002df49   Jeff Layton   cifs: add routine...
3698
3699
3700
3701
3702
3703
3704
3705
  	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...
3706
  		newtlink->tl_uid = fsuid;
9d002df49   Jeff Layton   cifs: add routine...
3707
3708
3709
3710
  		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...
3711
3712
  		spin_lock(&cifs_sb->tlink_tree_lock);
  		/* was one inserted after previous search? */
b647c35f7   Jeff Layton   cifs: convert tli...
3713
  		tlink = tlink_rb_search(&cifs_sb->tlink_tree, fsuid);
9d002df49   Jeff Layton   cifs: add routine...
3714
3715
3716
  		if (tlink) {
  			cifs_get_tlink(tlink);
  			spin_unlock(&cifs_sb->tlink_tree_lock);
9d002df49   Jeff Layton   cifs: add routine...
3717
3718
3719
  			kfree(newtlink);
  			goto wait_for_construction;
  		}
9d002df49   Jeff Layton   cifs: add routine...
3720
  		tlink = newtlink;
b647c35f7   Jeff Layton   cifs: convert tli...
3721
3722
  		tlink_rb_insert(&cifs_sb->tlink_tree, tlink);
  		spin_unlock(&cifs_sb->tlink_tree_lock);
9d002df49   Jeff Layton   cifs: add routine...
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
3747
3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
  	} 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...
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
  
  /*
   * 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...
3768
3769
3770
3771
  	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...
3772

b647c35f7   Jeff Layton   cifs: convert tli...
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
  	/*
  	 * 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...
3791

b647c35f7   Jeff Layton   cifs: convert tli...
3792
3793
3794
3795
3796
3797
3798
3799
3800
  		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...
3801
3802
3803
3804
  
  	queue_delayed_work(system_nrt_wq, &cifs_sb->prune_tlinks,
  				TLINK_IDLE_EXPIRE);
  }