[CIFS] build break
[linux-2.6-block.git] / fs / cifs / connect.c
CommitLineData
1da177e4
LT
1/*
2 * fs/cifs/connect.c
3 *
75865f8c 4 * Copyright (C) International Business Machines Corp., 2002,2007
1da177e4
LT
5 * Author(s): Steve French (sfrench@us.ibm.com)
6 *
7 * This library is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as published
9 * by the Free Software Foundation; either version 2.1 of the License, or
10 * (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
15 * the GNU Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this library; if not, write to the Free Software
fb8c4b14 19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
1da177e4
LT
20 */
21#include <linux/fs.h>
22#include <linux/net.h>
23#include <linux/string.h>
24#include <linux/list.h>
25#include <linux/wait.h>
26#include <linux/ipv6.h>
27#include <linux/pagemap.h>
28#include <linux/ctype.h>
29#include <linux/utsname.h>
30#include <linux/mempool.h>
b8643e1b 31#include <linux/delay.h>
f191401f 32#include <linux/completion.h>
aaf737ad 33#include <linux/kthread.h>
0ae0efad 34#include <linux/pagevec.h>
7dfb7103 35#include <linux/freezer.h>
1da177e4
LT
36#include <asm/uaccess.h>
37#include <asm/processor.h>
38#include "cifspdu.h"
39#include "cifsglob.h"
40#include "cifsproto.h"
41#include "cifs_unicode.h"
42#include "cifs_debug.h"
43#include "cifs_fs_sb.h"
44#include "ntlmssp.h"
45#include "nterr.h"
46#include "rfc1002pdu.h"
a2653eba 47#include "cn_cifs.h"
1da177e4
LT
48
49#define CIFS_PORT 445
50#define RFC1001_PORT 139
51
f191401f
SF
52static DECLARE_COMPLETION(cifsd_complete);
53
1da177e4
LT
54extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8,
55 unsigned char *p24);
56
57extern mempool_t *cifs_req_poolp;
58
59struct smb_vol {
60 char *username;
61 char *password;
62 char *domainname;
63 char *UNC;
64 char *UNCip;
65 char *in6_addr; /* ipv6 address as human readable form of in6_addr */
66 char *iocharset; /* local code page for mapping to and from Unicode */
67 char source_rfc1001_name[16]; /* netbios name of client */
a10faeb2 68 char target_rfc1001_name[16]; /* netbios name of server for Win9x/ME */
1da177e4
LT
69 uid_t linux_uid;
70 gid_t linux_gid;
71 mode_t file_mode;
72 mode_t dir_mode;
189acaae 73 unsigned secFlg;
1da177e4
LT
74 unsigned rw:1;
75 unsigned retry:1;
76 unsigned intr:1;
77 unsigned setuids:1;
4523cc30
SF
78 unsigned override_uid:1;
79 unsigned override_gid:1;
1da177e4
LT
80 unsigned noperm:1;
81 unsigned no_psx_acl:1; /* set if posix acl support should be disabled */
0a4b92c0 82 unsigned cifs_acl:1;
1da177e4
LT
83 unsigned no_xattr:1; /* set if xattr (EA) support should be disabled*/
84 unsigned server_ino:1; /* use inode numbers from server ie UniqueId */
85 unsigned direct_io:1;
6a0b4824 86 unsigned remap:1; /* set to remap seven reserved chars in filenames */
ac67055e 87 unsigned posix_paths:1; /* unset to not ask for posix pathnames. */
c18c842b 88 unsigned no_linux_ext:1;
d7245c2c 89 unsigned sfu_emul:1;
bf820679 90 unsigned nullauth:1; /* attempt to authenticate with null user */
c46fa8ac
SF
91 unsigned nocase; /* request case insensitive filenames */
92 unsigned nobrl; /* disable sending byte range locks to srv */
1da177e4
LT
93 unsigned int rsize;
94 unsigned int wsize;
95 unsigned int sockopt;
96 unsigned short int port;
fb8c4b14 97 char *prepath;
1da177e4
LT
98};
99
fb8c4b14 100static int ipv4_connect(struct sockaddr_in *psin_server,
1da177e4 101 struct socket **csocket,
fb8c4b14
SF
102 char *netb_name,
103 char *server_netb_name);
104static int ipv6_connect(struct sockaddr_in6 *psin_server,
1da177e4
LT
105 struct socket **csocket);
106
107
fb8c4b14 108 /*
1da177e4 109 * cifs tcp session reconnection
fb8c4b14 110 *
1da177e4
LT
111 * mark tcp session as reconnecting so temporarily locked
112 * mark all smb sessions as reconnecting for tcp session
113 * reconnect tcp session
114 * wake up waiters on reconnection? - (not needed currently)
115 */
116
2cd646a2 117static int
1da177e4
LT
118cifs_reconnect(struct TCP_Server_Info *server)
119{
120 int rc = 0;
121 struct list_head *tmp;
122 struct cifsSesInfo *ses;
123 struct cifsTconInfo *tcon;
fb8c4b14 124 struct mid_q_entry *mid_entry;
50c2f753 125
1da177e4 126 spin_lock(&GlobalMid_Lock);
26f57364 127 if (kthread_should_stop()) {
fb8c4b14 128 /* the demux thread will exit normally
1da177e4
LT
129 next time through the loop */
130 spin_unlock(&GlobalMid_Lock);
131 return rc;
132 } else
133 server->tcpStatus = CifsNeedReconnect;
134 spin_unlock(&GlobalMid_Lock);
135 server->maxBuf = 0;
136
e4eb295d 137 cFYI(1, ("Reconnecting tcp session"));
1da177e4
LT
138
139 /* before reconnecting the tcp session, mark the smb session (uid)
140 and the tid bad so they are not used until reconnected */
141 read_lock(&GlobalSMBSeslock);
142 list_for_each(tmp, &GlobalSMBSessionList) {
143 ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
144 if (ses->server) {
145 if (ses->server == server) {
146 ses->status = CifsNeedReconnect;
147 ses->ipc_tid = 0;
148 }
149 }
150 /* else tcp and smb sessions need reconnection */
151 }
152 list_for_each(tmp, &GlobalTreeConnectionList) {
153 tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
26f57364 154 if ((tcon) && (tcon->ses) && (tcon->ses->server == server))
1da177e4 155 tcon->tidStatus = CifsNeedReconnect;
1da177e4
LT
156 }
157 read_unlock(&GlobalSMBSeslock);
158 /* do not want to be sending data on a socket we are freeing */
fb8c4b14
SF
159 down(&server->tcpSem);
160 if (server->ssocket) {
467a8f8d 161 cFYI(1, ("State: 0x%x Flags: 0x%lx", server->ssocket->state,
1da177e4 162 server->ssocket->flags));
fb8c4b14
SF
163 server->ssocket->ops->shutdown(server->ssocket, SEND_SHUTDOWN);
164 cFYI(1, ("Post shutdown state: 0x%x Flags: 0x%lx",
467a8f8d 165 server->ssocket->state,
1da177e4
LT
166 server->ssocket->flags));
167 sock_release(server->ssocket);
168 server->ssocket = NULL;
169 }
170
171 spin_lock(&GlobalMid_Lock);
172 list_for_each(tmp, &server->pending_mid_q) {
173 mid_entry = list_entry(tmp, struct
174 mid_q_entry,
175 qhead);
fb8c4b14
SF
176 if (mid_entry) {
177 if (mid_entry->midState == MID_REQUEST_SUBMITTED) {
09d1db5c
SF
178 /* Mark other intransit requests as needing
179 retry so we do not immediately mark the
180 session bad again (ie after we reconnect
181 below) as they timeout too */
1da177e4
LT
182 mid_entry->midState = MID_RETRY_NEEDED;
183 }
184 }
185 }
186 spin_unlock(&GlobalMid_Lock);
fb8c4b14 187 up(&server->tcpSem);
1da177e4 188
26f57364 189 while ((!kthread_should_stop()) && (server->tcpStatus != CifsGood)) {
6c3d8909 190 try_to_freeze();
fb8c4b14
SF
191 if (server->protocolType == IPV6) {
192 rc = ipv6_connect(&server->addr.sockAddr6,
193 &server->ssocket);
1da177e4 194 } else {
fb8c4b14 195 rc = ipv4_connect(&server->addr.sockAddr,
1da177e4 196 &server->ssocket,
a10faeb2
SF
197 server->workstation_RFC1001_name,
198 server->server_RFC1001_name);
1da177e4 199 }
fb8c4b14
SF
200 if (rc) {
201 cFYI(1, ("reconnect error %d", rc));
0cb766ae 202 msleep(3000);
1da177e4
LT
203 } else {
204 atomic_inc(&tcpSesReconnectCount);
205 spin_lock(&GlobalMid_Lock);
26f57364 206 if (!kthread_should_stop())
1da177e4 207 server->tcpStatus = CifsGood;
ad009ac9 208 server->sequence_number = 0;
fb8c4b14 209 spin_unlock(&GlobalMid_Lock);
1da177e4
LT
210 /* atomic_set(&server->inFlight,0);*/
211 wake_up(&server->response_q);
212 }
213 }
214 return rc;
215}
216
fb8c4b14 217/*
e4eb295d
SF
218 return codes:
219 0 not a transact2, or all data present
220 >0 transact2 with that much data missing
221 -EINVAL = invalid transact2
222
223 */
fb8c4b14 224static int check2ndT2(struct smb_hdr *pSMB, unsigned int maxBufSize)
e4eb295d 225{
fb8c4b14
SF
226 struct smb_t2_rsp *pSMBt;
227 int total_data_size;
e4eb295d
SF
228 int data_in_this_rsp;
229 int remaining;
230
fb8c4b14 231 if (pSMB->Command != SMB_COM_TRANSACTION2)
e4eb295d
SF
232 return 0;
233
fb8c4b14
SF
234 /* check for plausible wct, bcc and t2 data and parm sizes */
235 /* check for parm and data offset going beyond end of smb */
236 if (pSMB->WordCount != 10) { /* coalesce_t2 depends on this */
467a8f8d 237 cFYI(1, ("invalid transact2 word count"));
e4eb295d
SF
238 return -EINVAL;
239 }
240
241 pSMBt = (struct smb_t2_rsp *)pSMB;
242
243 total_data_size = le16_to_cpu(pSMBt->t2_rsp.TotalDataCount);
244 data_in_this_rsp = le16_to_cpu(pSMBt->t2_rsp.DataCount);
245
246 remaining = total_data_size - data_in_this_rsp;
247
fb8c4b14 248 if (remaining == 0)
e4eb295d 249 return 0;
fb8c4b14 250 else if (remaining < 0) {
467a8f8d 251 cFYI(1, ("total data %d smaller than data in frame %d",
e4eb295d
SF
252 total_data_size, data_in_this_rsp));
253 return -EINVAL;
254 } else {
467a8f8d 255 cFYI(1, ("missing %d bytes from transact2, check next response",
e4eb295d 256 remaining));
fb8c4b14
SF
257 if (total_data_size > maxBufSize) {
258 cERROR(1, ("TotalDataSize %d is over maximum buffer %d",
259 total_data_size, maxBufSize));
260 return -EINVAL;
e4eb295d
SF
261 }
262 return remaining;
263 }
264}
265
fb8c4b14 266static int coalesce_t2(struct smb_hdr *psecond, struct smb_hdr *pTargetSMB)
e4eb295d
SF
267{
268 struct smb_t2_rsp *pSMB2 = (struct smb_t2_rsp *)psecond;
269 struct smb_t2_rsp *pSMBt = (struct smb_t2_rsp *)pTargetSMB;
270 int total_data_size;
271 int total_in_buf;
272 int remaining;
273 int total_in_buf2;
fb8c4b14
SF
274 char *data_area_of_target;
275 char *data_area_of_buf2;
e4eb295d
SF
276 __u16 byte_count;
277
278 total_data_size = le16_to_cpu(pSMBt->t2_rsp.TotalDataCount);
279
fb8c4b14 280 if (total_data_size != le16_to_cpu(pSMB2->t2_rsp.TotalDataCount)) {
63135e08 281 cFYI(1, ("total data size of primary and secondary t2 differ"));
e4eb295d
SF
282 }
283
284 total_in_buf = le16_to_cpu(pSMBt->t2_rsp.DataCount);
285
286 remaining = total_data_size - total_in_buf;
50c2f753 287
fb8c4b14 288 if (remaining < 0)
e4eb295d
SF
289 return -EINVAL;
290
fb8c4b14 291 if (remaining == 0) /* nothing to do, ignore */
e4eb295d 292 return 0;
50c2f753 293
e4eb295d 294 total_in_buf2 = le16_to_cpu(pSMB2->t2_rsp.DataCount);
fb8c4b14 295 if (remaining < total_in_buf2) {
467a8f8d 296 cFYI(1, ("transact2 2nd response contains too much data"));
e4eb295d
SF
297 }
298
299 /* find end of first SMB data area */
fb8c4b14 300 data_area_of_target = (char *)&pSMBt->hdr.Protocol +
e4eb295d
SF
301 le16_to_cpu(pSMBt->t2_rsp.DataOffset);
302 /* validate target area */
303
304 data_area_of_buf2 = (char *) &pSMB2->hdr.Protocol +
fb8c4b14 305 le16_to_cpu(pSMB2->t2_rsp.DataOffset);
e4eb295d
SF
306
307 data_area_of_target += total_in_buf;
308
309 /* copy second buffer into end of first buffer */
fb8c4b14 310 memcpy(data_area_of_target, data_area_of_buf2, total_in_buf2);
e4eb295d
SF
311 total_in_buf += total_in_buf2;
312 pSMBt->t2_rsp.DataCount = cpu_to_le16(total_in_buf);
313 byte_count = le16_to_cpu(BCC_LE(pTargetSMB));
314 byte_count += total_in_buf2;
315 BCC_LE(pTargetSMB) = cpu_to_le16(byte_count);
316
70ca734a 317 byte_count = pTargetSMB->smb_buf_length;
e4eb295d
SF
318 byte_count += total_in_buf2;
319
320 /* BB also add check that we are not beyond maximum buffer size */
50c2f753 321
70ca734a 322 pTargetSMB->smb_buf_length = byte_count;
e4eb295d 323
fb8c4b14 324 if (remaining == total_in_buf2) {
467a8f8d 325 cFYI(1, ("found the last secondary response"));
e4eb295d
SF
326 return 0; /* we are done */
327 } else /* more responses to go */
328 return 1;
329
330}
331
1da177e4
LT
332static int
333cifs_demultiplex_thread(struct TCP_Server_Info *server)
334{
335 int length;
336 unsigned int pdu_length, total_read;
337 struct smb_hdr *smb_buffer = NULL;
b8643e1b
SF
338 struct smb_hdr *bigbuf = NULL;
339 struct smb_hdr *smallbuf = NULL;
1da177e4
LT
340 struct msghdr smb_msg;
341 struct kvec iov;
342 struct socket *csocket = server->ssocket;
343 struct list_head *tmp;
344 struct cifsSesInfo *ses;
345 struct task_struct *task_to_wake = NULL;
346 struct mid_q_entry *mid_entry;
70ca734a 347 char temp;
b8643e1b 348 int isLargeBuf = FALSE;
e4eb295d
SF
349 int isMultiRsp;
350 int reconnect;
1da177e4 351
1da177e4
LT
352 current->flags |= PF_MEMALLOC;
353 server->tsk = current; /* save process info to wake at shutdown */
354 cFYI(1, ("Demultiplex PID: %d", current->pid));
fb8c4b14 355 write_lock(&GlobalSMBSeslock);
1da177e4
LT
356 atomic_inc(&tcpSesAllocCount);
357 length = tcpSesAllocCount.counter;
358 write_unlock(&GlobalSMBSeslock);
f191401f 359 complete(&cifsd_complete);
26f57364
SF
360 if (length > 1)
361 mempool_resize(cifs_req_poolp, length + cifs_min_rcv,
362 GFP_KERNEL);
1da177e4 363
83144186 364 set_freezable();
aaf737ad 365 while (!kthread_should_stop()) {
ede1327e
SF
366 if (try_to_freeze())
367 continue;
b8643e1b
SF
368 if (bigbuf == NULL) {
369 bigbuf = cifs_buf_get();
0fd1ffe0
PM
370 if (!bigbuf) {
371 cERROR(1, ("No memory for large SMB response"));
b8643e1b
SF
372 msleep(3000);
373 /* retry will check if exiting */
374 continue;
375 }
0fd1ffe0
PM
376 } else if (isLargeBuf) {
377 /* we are reusing a dirty large buf, clear its start */
26f57364 378 memset(bigbuf, 0, sizeof(struct smb_hdr));
1da177e4 379 }
b8643e1b
SF
380
381 if (smallbuf == NULL) {
382 smallbuf = cifs_small_buf_get();
0fd1ffe0
PM
383 if (!smallbuf) {
384 cERROR(1, ("No memory for SMB response"));
b8643e1b
SF
385 msleep(1000);
386 /* retry will check if exiting */
387 continue;
388 }
389 /* beginning of smb buffer is cleared in our buf_get */
390 } else /* if existing small buf clear beginning */
26f57364 391 memset(smallbuf, 0, sizeof(struct smb_hdr));
b8643e1b
SF
392
393 isLargeBuf = FALSE;
e4eb295d 394 isMultiRsp = FALSE;
b8643e1b 395 smb_buffer = smallbuf;
1da177e4
LT
396 iov.iov_base = smb_buffer;
397 iov.iov_len = 4;
398 smb_msg.msg_control = NULL;
399 smb_msg.msg_controllen = 0;
f01d5e14
SF
400 pdu_length = 4; /* enough to get RFC1001 header */
401incomplete_rcv:
1da177e4
LT
402 length =
403 kernel_recvmsg(csocket, &smb_msg,
f01d5e14 404 &iov, 1, pdu_length, 0 /* BB other flags? */);
1da177e4 405
26f57364 406 if (kthread_should_stop()) {
1da177e4
LT
407 break;
408 } else if (server->tcpStatus == CifsNeedReconnect) {
0fd1ffe0 409 cFYI(1, ("Reconnect after server stopped responding"));
1da177e4 410 cifs_reconnect(server);
0fd1ffe0 411 cFYI(1, ("call to reconnect done"));
1da177e4
LT
412 csocket = server->ssocket;
413 continue;
414 } else if ((length == -ERESTARTSYS) || (length == -EAGAIN)) {
b8643e1b 415 msleep(1); /* minimum sleep to prevent looping
1da177e4
LT
416 allowing socket to clear and app threads to set
417 tcpStatus CifsNeedReconnect if server hung */
418 continue;
419 } else if (length <= 0) {
0fd1ffe0
PM
420 if (server->tcpStatus == CifsNew) {
421 cFYI(1, ("tcp session abend after SMBnegprot"));
09d1db5c
SF
422 /* some servers kill the TCP session rather than
423 returning an SMB negprot error, in which
424 case reconnecting here is not going to help,
425 and so simply return error to mount */
1da177e4
LT
426 break;
427 }
0fd1ffe0 428 if (!try_to_freeze() && (length == -EINTR)) {
467a8f8d 429 cFYI(1, ("cifsd thread killed"));
1da177e4
LT
430 break;
431 }
467a8f8d 432 cFYI(1, ("Reconnect after unexpected peek error %d",
57337e42 433 length));
1da177e4
LT
434 cifs_reconnect(server);
435 csocket = server->ssocket;
436 wake_up(&server->response_q);
437 continue;
46810cbf 438 } else if (length < 4) {
f01d5e14 439 cFYI(1, ("less than four bytes received (%d bytes)",
46810cbf 440 length));
f01d5e14 441 pdu_length -= length;
f01d5e14
SF
442 msleep(1);
443 goto incomplete_rcv;
46810cbf 444 }
1da177e4 445
70ca734a
SF
446 /* The right amount was read from socket - 4 bytes */
447 /* so we can now interpret the length field */
46810cbf 448
70ca734a
SF
449 /* the first byte big endian of the length field,
450 is actually not part of the length but the type
451 with the most common, zero, as regular data */
452 temp = *((char *) smb_buffer);
46810cbf 453
fb8c4b14 454 /* Note that FC 1001 length is big endian on the wire,
70ca734a
SF
455 but we convert it here so it is always manipulated
456 as host byte order */
46810cbf 457 pdu_length = ntohl(smb_buffer->smb_buf_length);
70ca734a
SF
458 smb_buffer->smb_buf_length = pdu_length;
459
467a8f8d 460 cFYI(1, ("rfc1002 length 0x%x", pdu_length+4));
46810cbf 461
70ca734a 462 if (temp == (char) RFC1002_SESSION_KEEP_ALIVE) {
fb8c4b14 463 continue;
70ca734a 464 } else if (temp == (char)RFC1002_POSITIVE_SESSION_RESPONSE) {
467a8f8d 465 cFYI(1, ("Good RFC 1002 session rsp"));
e4eb295d 466 continue;
70ca734a 467 } else if (temp == (char)RFC1002_NEGATIVE_SESSION_RESPONSE) {
fb8c4b14 468 /* we get this from Windows 98 instead of
46810cbf 469 an error on SMB negprot response */
fb8c4b14 470 cFYI(1, ("Negative RFC1002 Session Response Error 0x%x)",
70ca734a 471 pdu_length));
fb8c4b14
SF
472 if (server->tcpStatus == CifsNew) {
473 /* if nack on negprot (rather than
46810cbf
SF
474 ret of smb negprot error) reconnecting
475 not going to help, ret error to mount */
476 break;
477 } else {
478 /* give server a second to
479 clean up before reconnect attempt */
480 msleep(1000);
481 /* always try 445 first on reconnect
482 since we get NACK on some if we ever
fb8c4b14 483 connected to port 139 (the NACK is
46810cbf
SF
484 since we do not begin with RFC1001
485 session initialize frame) */
fb8c4b14 486 server->addr.sockAddr.sin_port =
46810cbf 487 htons(CIFS_PORT);
1da177e4
LT
488 cifs_reconnect(server);
489 csocket = server->ssocket;
46810cbf 490 wake_up(&server->response_q);
1da177e4 491 continue;
46810cbf 492 }
70ca734a 493 } else if (temp != (char) 0) {
fb8c4b14 494 cERROR(1, ("Unknown RFC 1002 frame"));
70ca734a
SF
495 cifs_dump_mem(" Received Data: ", (char *)smb_buffer,
496 length);
46810cbf
SF
497 cifs_reconnect(server);
498 csocket = server->ssocket;
499 continue;
e4eb295d
SF
500 }
501
502 /* else we have an SMB response */
fb8c4b14 503 if ((pdu_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) ||
26f57364 504 (pdu_length < sizeof(struct smb_hdr) - 1 - 4)) {
e4eb295d 505 cERROR(1, ("Invalid size SMB length %d pdu_length %d",
46810cbf 506 length, pdu_length+4));
e4eb295d
SF
507 cifs_reconnect(server);
508 csocket = server->ssocket;
509 wake_up(&server->response_q);
510 continue;
fb8c4b14 511 }
e4eb295d
SF
512
513 /* else length ok */
514 reconnect = 0;
515
fb8c4b14 516 if (pdu_length > MAX_CIFS_SMALL_BUFFER_SIZE - 4) {
e4eb295d
SF
517 isLargeBuf = TRUE;
518 memcpy(bigbuf, smallbuf, 4);
519 smb_buffer = bigbuf;
520 }
521 length = 0;
522 iov.iov_base = 4 + (char *)smb_buffer;
523 iov.iov_len = pdu_length;
fb8c4b14 524 for (total_read = 0; total_read < pdu_length;
e4eb295d
SF
525 total_read += length) {
526 length = kernel_recvmsg(csocket, &smb_msg, &iov, 1,
527 pdu_length - total_read, 0);
26f57364 528 if (kthread_should_stop() ||
e4eb295d
SF
529 (length == -EINTR)) {
530 /* then will exit */
531 reconnect = 2;
532 break;
533 } else if (server->tcpStatus == CifsNeedReconnect) {
46810cbf
SF
534 cifs_reconnect(server);
535 csocket = server->ssocket;
fb8c4b14 536 /* Reconnect wakes up rspns q */
e4eb295d
SF
537 /* Now we will reread sock */
538 reconnect = 1;
539 break;
fb8c4b14 540 } else if ((length == -ERESTARTSYS) ||
e4eb295d
SF
541 (length == -EAGAIN)) {
542 msleep(1); /* minimum sleep to prevent looping,
fb8c4b14 543 allowing socket to clear and app
e4eb295d
SF
544 threads to set tcpStatus
545 CifsNeedReconnect if server hung*/
46810cbf 546 continue;
e4eb295d 547 } else if (length <= 0) {
fb8c4b14 548 cERROR(1, ("Received no data, expecting %d",
e4eb295d
SF
549 pdu_length - total_read));
550 cifs_reconnect(server);
551 csocket = server->ssocket;
552 reconnect = 1;
553 break;
46810cbf 554 }
e4eb295d 555 }
fb8c4b14 556 if (reconnect == 2)
e4eb295d 557 break;
fb8c4b14 558 else if (reconnect == 1)
e4eb295d 559 continue;
1da177e4 560
e4eb295d 561 length += 4; /* account for rfc1002 hdr */
50c2f753 562
09d1db5c 563
e4eb295d 564 dump_smb(smb_buffer, length);
184ed211 565 if (checkSMB(smb_buffer, smb_buffer->Mid, total_read+4)) {
b387eaeb 566 cifs_dump_mem("Bad SMB: ", smb_buffer, 48);
e4eb295d
SF
567 continue;
568 }
1da177e4 569
e4eb295d
SF
570
571 task_to_wake = NULL;
572 spin_lock(&GlobalMid_Lock);
573 list_for_each(tmp, &server->pending_mid_q) {
574 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
575
50c2f753 576 if ((mid_entry->mid == smb_buffer->Mid) &&
e4eb295d
SF
577 (mid_entry->midState == MID_REQUEST_SUBMITTED) &&
578 (mid_entry->command == smb_buffer->Command)) {
fb8c4b14 579 if (check2ndT2(smb_buffer,server->maxBuf) > 0) {
e4eb295d 580 /* We have a multipart transact2 resp */
cd63499c 581 isMultiRsp = TRUE;
fb8c4b14 582 if (mid_entry->resp_buf) {
e4eb295d 583 /* merge response - fix up 1st*/
50c2f753 584 if (coalesce_t2(smb_buffer,
e4eb295d 585 mid_entry->resp_buf)) {
3979877e 586 mid_entry->multiRsp = 1;
e4eb295d
SF
587 break;
588 } else {
589 /* all parts received */
3979877e 590 mid_entry->multiEnd = 1;
50c2f753 591 goto multi_t2_fnd;
e4eb295d
SF
592 }
593 } else {
fb8c4b14 594 if (!isLargeBuf) {
e4eb295d
SF
595 cERROR(1,("1st trans2 resp needs bigbuf"));
596 /* BB maybe we can fix this up, switch
50c2f753 597 to already allocated large buffer? */
e4eb295d 598 } else {
cd63499c 599 /* Have first buffer */
e4eb295d
SF
600 mid_entry->resp_buf =
601 smb_buffer;
602 mid_entry->largeBuf = 1;
e4eb295d
SF
603 bigbuf = NULL;
604 }
605 }
606 break;
50c2f753 607 }
e4eb295d 608 mid_entry->resp_buf = smb_buffer;
fb8c4b14 609 if (isLargeBuf)
e4eb295d 610 mid_entry->largeBuf = 1;
46810cbf 611 else
e4eb295d
SF
612 mid_entry->largeBuf = 0;
613multi_t2_fnd:
614 task_to_wake = mid_entry->tsk;
615 mid_entry->midState = MID_RESPONSE_RECEIVED;
1047abc1
SF
616#ifdef CONFIG_CIFS_STATS2
617 mid_entry->when_received = jiffies;
618#endif
3a5ff61c
SF
619 /* so we do not time out requests to server
620 which is still responding (since server could
621 be busy but not dead) */
622 server->lstrp = jiffies;
e4eb295d 623 break;
46810cbf 624 }
1da177e4 625 }
e4eb295d
SF
626 spin_unlock(&GlobalMid_Lock);
627 if (task_to_wake) {
cd63499c 628 /* Was previous buf put in mpx struct for multi-rsp? */
fb8c4b14 629 if (!isMultiRsp) {
cd63499c 630 /* smb buffer will be freed by user thread */
26f57364 631 if (isLargeBuf)
cd63499c 632 bigbuf = NULL;
26f57364 633 else
cd63499c
SF
634 smallbuf = NULL;
635 }
e4eb295d 636 wake_up_process(task_to_wake);
d7c8c94d 637 } else if ((is_valid_oplock_break(smb_buffer, server) == FALSE)
50c2f753
SF
638 && (isMultiRsp == FALSE)) {
639 cERROR(1, ("No task to wake, unknown frame received! "
640 "NumMids %d", midCount.counter));
641 cifs_dump_mem("Received Data is: ", (char *)smb_buffer,
70ca734a 642 sizeof(struct smb_hdr));
3979877e
SF
643#ifdef CONFIG_CIFS_DEBUG2
644 cifs_dump_detail(smb_buffer);
645 cifs_dump_mids(server);
646#endif /* CIFS_DEBUG2 */
50c2f753 647
e4eb295d
SF
648 }
649 } /* end while !EXITING */
650
1da177e4
LT
651 spin_lock(&GlobalMid_Lock);
652 server->tcpStatus = CifsExiting;
653 server->tsk = NULL;
31ca3bc3
SF
654 /* check if we have blocked requests that need to free */
655 /* Note that cifs_max_pending is normally 50, but
656 can be set at module install time to as little as two */
fb8c4b14 657 if (atomic_read(&server->inFlight) >= cifs_max_pending)
31ca3bc3
SF
658 atomic_set(&server->inFlight, cifs_max_pending - 1);
659 /* We do not want to set the max_pending too low or we
660 could end up with the counter going negative */
1da177e4 661 spin_unlock(&GlobalMid_Lock);
50c2f753 662 /* Although there should not be any requests blocked on
1da177e4 663 this queue it can not hurt to be paranoid and try to wake up requests
09d1db5c 664 that may haven been blocked when more than 50 at time were on the wire
1da177e4
LT
665 to the same server - they now will see the session is in exit state
666 and get out of SendReceive. */
667 wake_up_all(&server->request_q);
668 /* give those requests time to exit */
b8643e1b 669 msleep(125);
50c2f753 670
fb8c4b14 671 if (server->ssocket) {
1da177e4
LT
672 sock_release(csocket);
673 server->ssocket = NULL;
674 }
b8643e1b 675 /* buffer usuallly freed in free_mid - need to free it here on exit */
a8a11d39
MK
676 cifs_buf_release(bigbuf);
677 if (smallbuf) /* no sense logging a debug message if NULL */
b8643e1b 678 cifs_small_buf_release(smallbuf);
1da177e4
LT
679
680 read_lock(&GlobalSMBSeslock);
681 if (list_empty(&server->pending_mid_q)) {
09d1db5c
SF
682 /* loop through server session structures attached to this and
683 mark them dead */
1da177e4
LT
684 list_for_each(tmp, &GlobalSMBSessionList) {
685 ses =
686 list_entry(tmp, struct cifsSesInfo,
687 cifsSessionList);
688 if (ses->server == server) {
689 ses->status = CifsExiting;
690 ses->server = NULL;
691 }
692 }
693 read_unlock(&GlobalSMBSeslock);
694 } else {
31ca3bc3
SF
695 /* although we can not zero the server struct pointer yet,
696 since there are active requests which may depnd on them,
697 mark the corresponding SMB sessions as exiting too */
698 list_for_each(tmp, &GlobalSMBSessionList) {
699 ses = list_entry(tmp, struct cifsSesInfo,
700 cifsSessionList);
26f57364 701 if (ses->server == server)
31ca3bc3 702 ses->status = CifsExiting;
31ca3bc3
SF
703 }
704
1da177e4
LT
705 spin_lock(&GlobalMid_Lock);
706 list_for_each(tmp, &server->pending_mid_q) {
707 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
708 if (mid_entry->midState == MID_REQUEST_SUBMITTED) {
50c2f753
SF
709 cFYI(1, ("Clearing Mid 0x%x - waking up ",
710 mid_entry->mid));
1da177e4 711 task_to_wake = mid_entry->tsk;
26f57364 712 if (task_to_wake)
1da177e4 713 wake_up_process(task_to_wake);
1da177e4
LT
714 }
715 }
716 spin_unlock(&GlobalMid_Lock);
717 read_unlock(&GlobalSMBSeslock);
1da177e4 718 /* 1/8th of sec is more than enough time for them to exit */
b8643e1b 719 msleep(125);
1da177e4
LT
720 }
721
f191401f 722 if (!list_empty(&server->pending_mid_q)) {
50c2f753 723 /* mpx threads have not exited yet give them
1da177e4 724 at least the smb send timeout time for long ops */
31ca3bc3
SF
725 /* due to delays on oplock break requests, we need
726 to wait at least 45 seconds before giving up
727 on a request getting a response and going ahead
728 and killing cifsd */
1da177e4 729 cFYI(1, ("Wait for exit from demultiplex thread"));
31ca3bc3 730 msleep(46000);
1da177e4
LT
731 /* if threads still have not exited they are probably never
732 coming home not much else we can do but free the memory */
733 }
1da177e4
LT
734
735 write_lock(&GlobalSMBSeslock);
736 atomic_dec(&tcpSesAllocCount);
737 length = tcpSesAllocCount.counter;
31ca3bc3
SF
738
739 /* last chance to mark ses pointers invalid
740 if there are any pointing to this (e.g
50c2f753 741 if a crazy root user tried to kill cifsd
31ca3bc3
SF
742 kernel thread explicitly this might happen) */
743 list_for_each(tmp, &GlobalSMBSessionList) {
744 ses = list_entry(tmp, struct cifsSesInfo,
745 cifsSessionList);
26f57364 746 if (ses->server == server)
31ca3bc3 747 ses->server = NULL;
31ca3bc3 748 }
1da177e4 749 write_unlock(&GlobalSMBSeslock);
31ca3bc3
SF
750
751 kfree(server);
26f57364
SF
752 if (length > 0)
753 mempool_resize(cifs_req_poolp, length + cifs_min_rcv,
754 GFP_KERNEL);
50c2f753 755
1da177e4
LT
756 return 0;
757}
758
1da177e4 759static int
50c2f753
SF
760cifs_parse_mount_options(char *options, const char *devname,
761 struct smb_vol *vol)
1da177e4
LT
762{
763 char *value;
764 char *data;
765 unsigned int temp_len, i, j;
766 char separator[2];
767
768 separator[0] = ',';
50c2f753 769 separator[1] = 0;
1da177e4 770
12e36b2f 771 if (Local_System_Name[0] != 0)
50c2f753 772 memcpy(vol->source_rfc1001_name, Local_System_Name, 15);
2cd646a2 773 else {
12e36b2f 774 char *nodename = utsname()->nodename;
50c2f753
SF
775 int n = strnlen(nodename, 15);
776 memset(vol->source_rfc1001_name, 0x20, 15);
777 for (i = 0; i < n; i++) {
2cd646a2
SF
778 /* does not have to be perfect mapping since field is
779 informational, only used for servers that do not support
780 port 445 and it can be overridden at mount time */
12e36b2f 781 vol->source_rfc1001_name[i] = toupper(nodename[i]);
2cd646a2 782 }
1da177e4
LT
783 }
784 vol->source_rfc1001_name[15] = 0;
a10faeb2
SF
785 /* null target name indicates to use *SMBSERVR default called name
786 if we end up sending RFC1001 session initialize */
787 vol->target_rfc1001_name[0] = 0;
1da177e4
LT
788 vol->linux_uid = current->uid; /* current->euid instead? */
789 vol->linux_gid = current->gid;
790 vol->dir_mode = S_IRWXUGO;
791 /* 2767 perms indicate mandatory locking support */
792 vol->file_mode = S_IALLUGO & ~(S_ISUID | S_IXGRP);
793
794 /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
795 vol->rw = TRUE;
ac67055e
JA
796 /* default is always to request posix paths. */
797 vol->posix_paths = 1;
798
1da177e4
LT
799 if (!options)
800 return 1;
801
50c2f753 802 if (strncmp(options, "sep=", 4) == 0) {
fb8c4b14 803 if (options[4] != 0) {
1da177e4
LT
804 separator[0] = options[4];
805 options += 5;
806 } else {
467a8f8d 807 cFYI(1, ("Null separator not allowed"));
1da177e4
LT
808 }
809 }
50c2f753 810
1da177e4
LT
811 while ((data = strsep(&options, separator)) != NULL) {
812 if (!*data)
813 continue;
814 if ((value = strchr(data, '=')) != NULL)
815 *value++ = '\0';
816
50c2f753
SF
817 /* Have to parse this before we parse for "user" */
818 if (strnicmp(data, "user_xattr", 10) == 0) {
1da177e4 819 vol->no_xattr = 0;
50c2f753 820 } else if (strnicmp(data, "nouser_xattr", 12) == 0) {
1da177e4
LT
821 vol->no_xattr = 1;
822 } else if (strnicmp(data, "user", 4) == 0) {
4b952a9b 823 if (!value) {
1da177e4
LT
824 printk(KERN_WARNING
825 "CIFS: invalid or missing username\n");
826 return 1; /* needs_arg; */
fb8c4b14 827 } else if (!*value) {
4b952a9b
SF
828 /* null user, ie anonymous, authentication */
829 vol->nullauth = 1;
1da177e4
LT
830 }
831 if (strnlen(value, 200) < 200) {
832 vol->username = value;
833 } else {
834 printk(KERN_WARNING "CIFS: username too long\n");
835 return 1;
836 }
837 } else if (strnicmp(data, "pass", 4) == 0) {
838 if (!value) {
839 vol->password = NULL;
840 continue;
fb8c4b14 841 } else if (value[0] == 0) {
1da177e4
LT
842 /* check if string begins with double comma
843 since that would mean the password really
844 does start with a comma, and would not
845 indicate an empty string */
fb8c4b14 846 if (value[1] != separator[0]) {
1da177e4
LT
847 vol->password = NULL;
848 continue;
849 }
850 }
851 temp_len = strlen(value);
852 /* removed password length check, NTLM passwords
853 can be arbitrarily long */
854
50c2f753 855 /* if comma in password, the string will be
1da177e4
LT
856 prematurely null terminated. Commas in password are
857 specified across the cifs mount interface by a double
858 comma ie ,, and a comma used as in other cases ie ','
859 as a parameter delimiter/separator is single and due
860 to the strsep above is temporarily zeroed. */
861
862 /* NB: password legally can have multiple commas and
863 the only illegal character in a password is null */
864
50c2f753 865 if ((value[temp_len] == 0) &&
09d1db5c 866 (value[temp_len+1] == separator[0])) {
1da177e4
LT
867 /* reinsert comma */
868 value[temp_len] = separator[0];
50c2f753
SF
869 temp_len += 2; /* move after second comma */
870 while (value[temp_len] != 0) {
1da177e4 871 if (value[temp_len] == separator[0]) {
50c2f753 872 if (value[temp_len+1] ==
09d1db5c
SF
873 separator[0]) {
874 /* skip second comma */
875 temp_len++;
50c2f753 876 } else {
1da177e4
LT
877 /* single comma indicating start
878 of next parm */
879 break;
880 }
881 }
882 temp_len++;
883 }
fb8c4b14 884 if (value[temp_len] == 0) {
1da177e4
LT
885 options = NULL;
886 } else {
887 value[temp_len] = 0;
888 /* point option to start of next parm */
889 options = value + temp_len + 1;
890 }
50c2f753 891 /* go from value to value + temp_len condensing
1da177e4
LT
892 double commas to singles. Note that this ends up
893 allocating a few bytes too many, which is ok */
e915fc49 894 vol->password = kzalloc(temp_len, GFP_KERNEL);
fb8c4b14 895 if (vol->password == NULL) {
50c2f753
SF
896 printk(KERN_WARNING "CIFS: no memory "
897 "for password\n");
433dc24f
SF
898 return 1;
899 }
50c2f753 900 for (i = 0, j = 0; i < temp_len; i++, j++) {
1da177e4 901 vol->password[j] = value[i];
fb8c4b14 902 if (value[i] == separator[0]
09d1db5c 903 && value[i+1] == separator[0]) {
1da177e4
LT
904 /* skip second comma */
905 i++;
906 }
907 }
908 vol->password[j] = 0;
909 } else {
e915fc49 910 vol->password = kzalloc(temp_len+1, GFP_KERNEL);
fb8c4b14 911 if (vol->password == NULL) {
50c2f753
SF
912 printk(KERN_WARNING "CIFS: no memory "
913 "for password\n");
433dc24f
SF
914 return 1;
915 }
1da177e4
LT
916 strcpy(vol->password, value);
917 }
918 } else if (strnicmp(data, "ip", 2) == 0) {
919 if (!value || !*value) {
920 vol->UNCip = NULL;
921 } else if (strnlen(value, 35) < 35) {
922 vol->UNCip = value;
923 } else {
50c2f753
SF
924 printk(KERN_WARNING "CIFS: ip address "
925 "too long\n");
1da177e4
LT
926 return 1;
927 }
50c2f753
SF
928 } else if (strnicmp(data, "sec", 3) == 0) {
929 if (!value || !*value) {
930 cERROR(1, ("no security value specified"));
931 continue;
932 } else if (strnicmp(value, "krb5i", 5) == 0) {
933 vol->secFlg |= CIFSSEC_MAY_KRB5 |
189acaae 934 CIFSSEC_MUST_SIGN;
bf820679 935 } else if (strnicmp(value, "krb5p", 5) == 0) {
50c2f753
SF
936 /* vol->secFlg |= CIFSSEC_MUST_SEAL |
937 CIFSSEC_MAY_KRB5; */
938 cERROR(1, ("Krb5 cifs privacy not supported"));
bf820679
SF
939 return 1;
940 } else if (strnicmp(value, "krb5", 4) == 0) {
750d1151 941 vol->secFlg |= CIFSSEC_MAY_KRB5;
bf820679 942 } else if (strnicmp(value, "ntlmv2i", 7) == 0) {
750d1151 943 vol->secFlg |= CIFSSEC_MAY_NTLMV2 |
189acaae 944 CIFSSEC_MUST_SIGN;
bf820679 945 } else if (strnicmp(value, "ntlmv2", 6) == 0) {
750d1151 946 vol->secFlg |= CIFSSEC_MAY_NTLMV2;
bf820679 947 } else if (strnicmp(value, "ntlmi", 5) == 0) {
750d1151 948 vol->secFlg |= CIFSSEC_MAY_NTLM |
189acaae 949 CIFSSEC_MUST_SIGN;
bf820679
SF
950 } else if (strnicmp(value, "ntlm", 4) == 0) {
951 /* ntlm is default so can be turned off too */
750d1151 952 vol->secFlg |= CIFSSEC_MAY_NTLM;
bf820679 953 } else if (strnicmp(value, "nontlm", 6) == 0) {
189acaae 954 /* BB is there a better way to do this? */
750d1151 955 vol->secFlg |= CIFSSEC_MAY_NTLMV2;
189acaae
SF
956#ifdef CONFIG_CIFS_WEAK_PW_HASH
957 } else if (strnicmp(value, "lanman", 6) == 0) {
50c2f753 958 vol->secFlg |= CIFSSEC_MAY_LANMAN;
189acaae 959#endif
bf820679 960 } else if (strnicmp(value, "none", 4) == 0) {
189acaae 961 vol->nullauth = 1;
50c2f753
SF
962 } else {
963 cERROR(1, ("bad security option: %s", value));
964 return 1;
965 }
1da177e4
LT
966 } else if ((strnicmp(data, "unc", 3) == 0)
967 || (strnicmp(data, "target", 6) == 0)
968 || (strnicmp(data, "path", 4) == 0)) {
969 if (!value || !*value) {
50c2f753
SF
970 printk(KERN_WARNING "CIFS: invalid path to "
971 "network resource\n");
1da177e4
LT
972 return 1; /* needs_arg; */
973 }
974 if ((temp_len = strnlen(value, 300)) < 300) {
50c2f753 975 vol->UNC = kmalloc(temp_len+1, GFP_KERNEL);
4523cc30 976 if (vol->UNC == NULL)
1da177e4 977 return 1;
50c2f753 978 strcpy(vol->UNC, value);
1da177e4
LT
979 if (strncmp(vol->UNC, "//", 2) == 0) {
980 vol->UNC[0] = '\\';
981 vol->UNC[1] = '\\';
50c2f753 982 } else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
1da177e4 983 printk(KERN_WARNING
50c2f753
SF
984 "CIFS: UNC Path does not begin "
985 "with // or \\\\ \n");
1da177e4
LT
986 return 1;
987 }
988 } else {
989 printk(KERN_WARNING "CIFS: UNC name too long\n");
990 return 1;
991 }
992 } else if ((strnicmp(data, "domain", 3) == 0)
993 || (strnicmp(data, "workgroup", 5) == 0)) {
994 if (!value || !*value) {
995 printk(KERN_WARNING "CIFS: invalid domain name\n");
996 return 1; /* needs_arg; */
997 }
998 /* BB are there cases in which a comma can be valid in
999 a domain name and need special handling? */
3979877e 1000 if (strnlen(value, 256) < 256) {
1da177e4
LT
1001 vol->domainname = value;
1002 cFYI(1, ("Domain name set"));
1003 } else {
50c2f753
SF
1004 printk(KERN_WARNING "CIFS: domain name too "
1005 "long\n");
1da177e4
LT
1006 return 1;
1007 }
50c2f753
SF
1008 } else if (strnicmp(data, "prefixpath", 10) == 0) {
1009 if (!value || !*value) {
1010 printk(KERN_WARNING
1011 "CIFS: invalid path prefix\n");
1012 return 1; /* needs_argument */
1013 }
1014 if ((temp_len = strnlen(value, 1024)) < 1024) {
4523cc30 1015 if (value[0] != '/')
2fe87f02 1016 temp_len++; /* missing leading slash */
50c2f753
SF
1017 vol->prepath = kmalloc(temp_len+1, GFP_KERNEL);
1018 if (vol->prepath == NULL)
1019 return 1;
4523cc30 1020 if (value[0] != '/') {
2fe87f02 1021 vol->prepath[0] = '/';
50c2f753 1022 strcpy(vol->prepath+1, value);
2fe87f02 1023 } else
50c2f753
SF
1024 strcpy(vol->prepath, value);
1025 cFYI(1, ("prefix path %s", vol->prepath));
1026 } else {
1027 printk(KERN_WARNING "CIFS: prefix too long\n");
1028 return 1;
1029 }
1da177e4
LT
1030 } else if (strnicmp(data, "iocharset", 9) == 0) {
1031 if (!value || !*value) {
63135e08
SF
1032 printk(KERN_WARNING "CIFS: invalid iocharset "
1033 "specified\n");
1da177e4
LT
1034 return 1; /* needs_arg; */
1035 }
1036 if (strnlen(value, 65) < 65) {
50c2f753 1037 if (strnicmp(value, "default", 7))
1da177e4 1038 vol->iocharset = value;
50c2f753
SF
1039 /* if iocharset not set then load_nls_default
1040 is used by caller */
1041 cFYI(1, ("iocharset set to %s", value));
1da177e4 1042 } else {
63135e08
SF
1043 printk(KERN_WARNING "CIFS: iocharset name "
1044 "too long.\n");
1da177e4
LT
1045 return 1;
1046 }
1047 } else if (strnicmp(data, "uid", 3) == 0) {
1048 if (value && *value) {
1049 vol->linux_uid =
1050 simple_strtoul(value, &value, 0);
4523cc30 1051 vol->override_uid = 1;
1da177e4
LT
1052 }
1053 } else if (strnicmp(data, "gid", 3) == 0) {
1054 if (value && *value) {
1055 vol->linux_gid =
1056 simple_strtoul(value, &value, 0);
4523cc30 1057 vol->override_gid = 1;
1da177e4
LT
1058 }
1059 } else if (strnicmp(data, "file_mode", 4) == 0) {
1060 if (value && *value) {
1061 vol->file_mode =
1062 simple_strtoul(value, &value, 0);
1063 }
1064 } else if (strnicmp(data, "dir_mode", 4) == 0) {
1065 if (value && *value) {
1066 vol->dir_mode =
1067 simple_strtoul(value, &value, 0);
1068 }
1069 } else if (strnicmp(data, "dirmode", 4) == 0) {
1070 if (value && *value) {
1071 vol->dir_mode =
1072 simple_strtoul(value, &value, 0);
1073 }
1074 } else if (strnicmp(data, "port", 4) == 0) {
1075 if (value && *value) {
1076 vol->port =
1077 simple_strtoul(value, &value, 0);
1078 }
1079 } else if (strnicmp(data, "rsize", 5) == 0) {
1080 if (value && *value) {
1081 vol->rsize =
1082 simple_strtoul(value, &value, 0);
1083 }
1084 } else if (strnicmp(data, "wsize", 5) == 0) {
1085 if (value && *value) {
1086 vol->wsize =
1087 simple_strtoul(value, &value, 0);
1088 }
1089 } else if (strnicmp(data, "sockopt", 5) == 0) {
1090 if (value && *value) {
1091 vol->sockopt =
1092 simple_strtoul(value, &value, 0);
1093 }
1094 } else if (strnicmp(data, "netbiosname", 4) == 0) {
1095 if (!value || !*value || (*value == ' ')) {
63135e08 1096 cFYI(1, ("invalid (empty) netbiosname"));
1da177e4 1097 } else {
50c2f753
SF
1098 memset(vol->source_rfc1001_name, 0x20, 15);
1099 for (i = 0; i < 15; i++) {
1100 /* BB are there cases in which a comma can be
1da177e4
LT
1101 valid in this workstation netbios name (and need
1102 special handling)? */
1103
1104 /* We do not uppercase netbiosname for user */
50c2f753 1105 if (value[i] == 0)
1da177e4 1106 break;
50c2f753
SF
1107 else
1108 vol->source_rfc1001_name[i] =
1109 value[i];
1da177e4
LT
1110 }
1111 /* The string has 16th byte zero still from
1112 set at top of the function */
50c2f753
SF
1113 if ((i == 15) && (value[i] != 0))
1114 printk(KERN_WARNING "CIFS: netbiosname"
1115 " longer than 15 truncated.\n");
a10faeb2
SF
1116 }
1117 } else if (strnicmp(data, "servern", 7) == 0) {
1118 /* servernetbiosname specified override *SMBSERVER */
1119 if (!value || !*value || (*value == ' ')) {
467a8f8d 1120 cFYI(1, ("empty server netbiosname specified"));
a10faeb2
SF
1121 } else {
1122 /* last byte, type, is 0x20 for servr type */
50c2f753 1123 memset(vol->target_rfc1001_name, 0x20, 16);
a10faeb2 1124
50c2f753 1125 for (i = 0; i < 15; i++) {
a10faeb2 1126 /* BB are there cases in which a comma can be
50c2f753
SF
1127 valid in this workstation netbios name
1128 (and need special handling)? */
a10faeb2 1129
50c2f753
SF
1130 /* user or mount helper must uppercase
1131 the netbiosname */
1132 if (value[i] == 0)
a10faeb2
SF
1133 break;
1134 else
50c2f753
SF
1135 vol->target_rfc1001_name[i] =
1136 value[i];
a10faeb2
SF
1137 }
1138 /* The string has 16th byte zero still from
1139 set at top of the function */
50c2f753
SF
1140 if ((i == 15) && (value[i] != 0))
1141 printk(KERN_WARNING "CIFS: server net"
1142 "biosname longer than 15 truncated.\n");
1da177e4
LT
1143 }
1144 } else if (strnicmp(data, "credentials", 4) == 0) {
1145 /* ignore */
1146 } else if (strnicmp(data, "version", 3) == 0) {
1147 /* ignore */
50c2f753 1148 } else if (strnicmp(data, "guest", 5) == 0) {
1da177e4
LT
1149 /* ignore */
1150 } else if (strnicmp(data, "rw", 2) == 0) {
1151 vol->rw = TRUE;
1152 } else if ((strnicmp(data, "suid", 4) == 0) ||
1153 (strnicmp(data, "nosuid", 6) == 0) ||
1154 (strnicmp(data, "exec", 4) == 0) ||
1155 (strnicmp(data, "noexec", 6) == 0) ||
1156 (strnicmp(data, "nodev", 5) == 0) ||
1157 (strnicmp(data, "noauto", 6) == 0) ||
1158 (strnicmp(data, "dev", 3) == 0)) {
1159 /* The mount tool or mount.cifs helper (if present)
50c2f753
SF
1160 uses these opts to set flags, and the flags are read
1161 by the kernel vfs layer before we get here (ie
1162 before read super) so there is no point trying to
1163 parse these options again and set anything and it
1164 is ok to just ignore them */
1da177e4
LT
1165 continue;
1166 } else if (strnicmp(data, "ro", 2) == 0) {
1167 vol->rw = FALSE;
1168 } else if (strnicmp(data, "hard", 4) == 0) {
1169 vol->retry = 1;
1170 } else if (strnicmp(data, "soft", 4) == 0) {
1171 vol->retry = 0;
1172 } else if (strnicmp(data, "perm", 4) == 0) {
1173 vol->noperm = 0;
1174 } else if (strnicmp(data, "noperm", 6) == 0) {
1175 vol->noperm = 1;
6a0b4824
SF
1176 } else if (strnicmp(data, "mapchars", 8) == 0) {
1177 vol->remap = 1;
1178 } else if (strnicmp(data, "nomapchars", 10) == 0) {
1179 vol->remap = 0;
50c2f753
SF
1180 } else if (strnicmp(data, "sfu", 3) == 0) {
1181 vol->sfu_emul = 1;
1182 } else if (strnicmp(data, "nosfu", 5) == 0) {
1183 vol->sfu_emul = 0;
ac67055e
JA
1184 } else if (strnicmp(data, "posixpaths", 10) == 0) {
1185 vol->posix_paths = 1;
1186 } else if (strnicmp(data, "noposixpaths", 12) == 0) {
1187 vol->posix_paths = 0;
c18c842b
SF
1188 } else if (strnicmp(data, "nounix", 6) == 0) {
1189 vol->no_linux_ext = 1;
1190 } else if (strnicmp(data, "nolinux", 7) == 0) {
1191 vol->no_linux_ext = 1;
50c2f753 1192 } else if ((strnicmp(data, "nocase", 6) == 0) ||
a10faeb2 1193 (strnicmp(data, "ignorecase", 10) == 0)) {
50c2f753 1194 vol->nocase = 1;
c46fa8ac
SF
1195 } else if (strnicmp(data, "brl", 3) == 0) {
1196 vol->nobrl = 0;
50c2f753 1197 } else if ((strnicmp(data, "nobrl", 5) == 0) ||
1c955187 1198 (strnicmp(data, "nolock", 6) == 0)) {
c46fa8ac 1199 vol->nobrl = 1;
d3485d37
SF
1200 /* turn off mandatory locking in mode
1201 if remote locking is turned off since the
1202 local vfs will do advisory */
50c2f753
SF
1203 if (vol->file_mode ==
1204 (S_IALLUGO & ~(S_ISUID | S_IXGRP)))
d3485d37 1205 vol->file_mode = S_IALLUGO;
1da177e4
LT
1206 } else if (strnicmp(data, "setuids", 7) == 0) {
1207 vol->setuids = 1;
1208 } else if (strnicmp(data, "nosetuids", 9) == 0) {
1209 vol->setuids = 0;
1210 } else if (strnicmp(data, "nohard", 6) == 0) {
1211 vol->retry = 0;
1212 } else if (strnicmp(data, "nosoft", 6) == 0) {
1213 vol->retry = 1;
1214 } else if (strnicmp(data, "nointr", 6) == 0) {
1215 vol->intr = 0;
1216 } else if (strnicmp(data, "intr", 4) == 0) {
1217 vol->intr = 1;
50c2f753 1218 } else if (strnicmp(data, "serverino", 7) == 0) {
1da177e4 1219 vol->server_ino = 1;
50c2f753 1220 } else if (strnicmp(data, "noserverino", 9) == 0) {
1da177e4 1221 vol->server_ino = 0;
50c2f753 1222 } else if (strnicmp(data, "cifsacl", 7) == 0) {
0a4b92c0
SF
1223 vol->cifs_acl = 1;
1224 } else if (strnicmp(data, "nocifsacl", 9) == 0) {
1225 vol->cifs_acl = 0;
50c2f753 1226 } else if (strnicmp(data, "acl", 3) == 0) {
1da177e4 1227 vol->no_psx_acl = 0;
50c2f753 1228 } else if (strnicmp(data, "noacl", 5) == 0) {
1da177e4 1229 vol->no_psx_acl = 1;
50c2f753 1230 } else if (strnicmp(data, "sign", 4) == 0) {
750d1151
SF
1231 vol->secFlg |= CIFSSEC_MUST_SIGN;
1232/* } else if (strnicmp(data, "seal",4) == 0) {
1233 vol->secFlg |= CIFSSEC_MUST_SEAL; */
50c2f753 1234 } else if (strnicmp(data, "direct", 6) == 0) {
1da177e4 1235 vol->direct_io = 1;
50c2f753 1236 } else if (strnicmp(data, "forcedirectio", 13) == 0) {
1da177e4 1237 vol->direct_io = 1;
50c2f753 1238 } else if (strnicmp(data, "in6_addr", 8) == 0) {
1da177e4
LT
1239 if (!value || !*value) {
1240 vol->in6_addr = NULL;
1241 } else if (strnlen(value, 49) == 48) {
1242 vol->in6_addr = value;
1243 } else {
50c2f753
SF
1244 printk(KERN_WARNING "CIFS: ip v6 address not "
1245 "48 characters long\n");
1da177e4
LT
1246 return 1;
1247 }
1248 } else if (strnicmp(data, "noac", 4) == 0) {
50c2f753
SF
1249 printk(KERN_WARNING "CIFS: Mount option noac not "
1250 "supported. Instead set "
1251 "/proc/fs/cifs/LookupCacheEnabled to 0\n");
1da177e4 1252 } else
50c2f753
SF
1253 printk(KERN_WARNING "CIFS: Unknown mount option %s\n",
1254 data);
1da177e4
LT
1255 }
1256 if (vol->UNC == NULL) {
4523cc30 1257 if (devname == NULL) {
50c2f753
SF
1258 printk(KERN_WARNING "CIFS: Missing UNC name for mount "
1259 "target\n");
1da177e4
LT
1260 return 1;
1261 }
1262 if ((temp_len = strnlen(devname, 300)) < 300) {
50c2f753 1263 vol->UNC = kmalloc(temp_len+1, GFP_KERNEL);
4523cc30 1264 if (vol->UNC == NULL)
1da177e4 1265 return 1;
50c2f753 1266 strcpy(vol->UNC, devname);
1da177e4
LT
1267 if (strncmp(vol->UNC, "//", 2) == 0) {
1268 vol->UNC[0] = '\\';
1269 vol->UNC[1] = '\\';
1270 } else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
50c2f753
SF
1271 printk(KERN_WARNING "CIFS: UNC Path does not "
1272 "begin with // or \\\\ \n");
1da177e4
LT
1273 return 1;
1274 }
1275 } else {
1276 printk(KERN_WARNING "CIFS: UNC name too long\n");
1277 return 1;
1278 }
1279 }
fb8c4b14 1280 if (vol->UNCip == NULL)
1da177e4
LT
1281 vol->UNCip = &vol->UNC[2];
1282
1283 return 0;
1284}
1285
1286static struct cifsSesInfo *
50c2f753 1287cifs_find_tcp_session(struct in_addr *target_ip_addr,
1da177e4
LT
1288 struct in6_addr *target_ip6_addr,
1289 char *userName, struct TCP_Server_Info **psrvTcp)
1290{
1291 struct list_head *tmp;
1292 struct cifsSesInfo *ses;
1293 *psrvTcp = NULL;
1294 read_lock(&GlobalSMBSeslock);
1295
1296 list_for_each(tmp, &GlobalSMBSessionList) {
1297 ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
1298 if (ses->server) {
50c2f753 1299 if ((target_ip_addr &&
1da177e4
LT
1300 (ses->server->addr.sockAddr.sin_addr.s_addr
1301 == target_ip_addr->s_addr)) || (target_ip6_addr
1302 && memcmp(&ses->server->addr.sockAddr6.sin6_addr,
50c2f753
SF
1303 target_ip6_addr, sizeof(*target_ip6_addr)))) {
1304 /* BB lock server and tcp session and increment
1305 use count here?? */
1306
1307 /* found a match on the TCP session */
1308 *psrvTcp = ses->server;
1309
1da177e4
LT
1310 /* BB check if reconnection needed */
1311 if (strncmp
1312 (ses->userName, userName,
1313 MAX_USERNAME_SIZE) == 0){
1314 read_unlock(&GlobalSMBSeslock);
50c2f753
SF
1315 /* Found exact match on both TCP and
1316 SMB sessions */
1317 return ses;
1da177e4
LT
1318 }
1319 }
1320 }
1321 /* else tcp and smb sessions need reconnection */
1322 }
1323 read_unlock(&GlobalSMBSeslock);
1324 return NULL;
1325}
1326
1327static struct cifsTconInfo *
1328find_unc(__be32 new_target_ip_addr, char *uncName, char *userName)
1329{
1330 struct list_head *tmp;
1331 struct cifsTconInfo *tcon;
1332
1333 read_lock(&GlobalSMBSeslock);
1334 list_for_each(tmp, &GlobalTreeConnectionList) {
e466e487 1335 cFYI(1, ("Next tcon"));
1da177e4
LT
1336 tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
1337 if (tcon->ses) {
1338 if (tcon->ses->server) {
1339 cFYI(1,
e466e487 1340 ("old ip addr: %x == new ip %x ?",
1da177e4
LT
1341 tcon->ses->server->addr.sockAddr.sin_addr.
1342 s_addr, new_target_ip_addr));
1343 if (tcon->ses->server->addr.sockAddr.sin_addr.
1344 s_addr == new_target_ip_addr) {
e466e487 1345 /* BB lock tcon, server and tcp session and increment use count here? */
1da177e4
LT
1346 /* found a match on the TCP session */
1347 /* BB check if reconnection needed */
50c2f753
SF
1348 cFYI(1,
1349 ("IP match, old UNC: %s new: %s",
1da177e4
LT
1350 tcon->treeName, uncName));
1351 if (strncmp
1352 (tcon->treeName, uncName,
1353 MAX_TREE_SIZE) == 0) {
1354 cFYI(1,
e466e487 1355 ("and old usr: %s new: %s",
1da177e4
LT
1356 tcon->treeName, uncName));
1357 if (strncmp
1358 (tcon->ses->userName,
1359 userName,
1360 MAX_USERNAME_SIZE) == 0) {
1361 read_unlock(&GlobalSMBSeslock);
e466e487
SF
1362 /* matched smb session
1363 (user name */
1364 return tcon;
1da177e4
LT
1365 }
1366 }
1367 }
1368 }
1369 }
1370 }
1371 read_unlock(&GlobalSMBSeslock);
1372 return NULL;
1373}
1374
1375int
1376connect_to_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
737b758c
SF
1377 const char *old_path, const struct nls_table *nls_codepage,
1378 int remap)
1da177e4
LT
1379{
1380 unsigned char *referrals = NULL;
1381 unsigned int num_referrals;
1382 int rc = 0;
1383
50c2f753 1384 rc = get_dfs_path(xid, pSesInfo, old_path, nls_codepage,
737b758c 1385 &num_referrals, &referrals, remap);
1da177e4
LT
1386
1387 /* BB Add in code to: if valid refrl, if not ip address contact
50c2f753 1388 the helper that resolves tcp names, mount to it, try to
1da177e4
LT
1389 tcon to it unmount it if fail */
1390
f99d49ad 1391 kfree(referrals);
1da177e4
LT
1392
1393 return rc;
1394}
1395
1396int
50c2f753
SF
1397get_dfs_path(int xid, struct cifsSesInfo *pSesInfo, const char *old_path,
1398 const struct nls_table *nls_codepage, unsigned int *pnum_referrals,
1399 unsigned char **preferrals, int remap)
1da177e4
LT
1400{
1401 char *temp_unc;
1402 int rc = 0;
1403
1404 *pnum_referrals = 0;
1405
1406 if (pSesInfo->ipc_tid == 0) {
1407 temp_unc = kmalloc(2 /* for slashes */ +
50c2f753
SF
1408 strnlen(pSesInfo->serverName,
1409 SERVER_NAME_LEN_WITH_NULL * 2)
1da177e4
LT
1410 + 1 + 4 /* slash IPC$ */ + 2,
1411 GFP_KERNEL);
1412 if (temp_unc == NULL)
1413 return -ENOMEM;
1414 temp_unc[0] = '\\';
1415 temp_unc[1] = '\\';
1416 strcpy(temp_unc + 2, pSesInfo->serverName);
1417 strcpy(temp_unc + 2 + strlen(pSesInfo->serverName), "\\IPC$");
1418 rc = CIFSTCon(xid, pSesInfo, temp_unc, NULL, nls_codepage);
1419 cFYI(1,
50c2f753 1420 ("CIFS Tcon rc = %d ipc_tid = %d", rc, pSesInfo->ipc_tid));
1da177e4
LT
1421 kfree(temp_unc);
1422 }
1423 if (rc == 0)
1424 rc = CIFSGetDFSRefer(xid, pSesInfo, old_path, preferrals,
737b758c 1425 pnum_referrals, nls_codepage, remap);
1da177e4
LT
1426
1427 return rc;
1428}
1429
1430/* See RFC1001 section 14 on representation of Netbios names */
50c2f753 1431static void rfc1002mangle(char *target, char *source, unsigned int length)
1da177e4 1432{
50c2f753 1433 unsigned int i, j;
1da177e4 1434
50c2f753 1435 for (i = 0, j = 0; i < (length); i++) {
1da177e4
LT
1436 /* mask a nibble at a time and encode */
1437 target[j] = 'A' + (0x0F & (source[i] >> 4));
1438 target[j+1] = 'A' + (0x0F & source[i]);
50c2f753 1439 j += 2;
1da177e4
LT
1440 }
1441
1442}
1443
1444
1445static int
50c2f753
SF
1446ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
1447 char *netbios_name, char *target_name)
1da177e4
LT
1448{
1449 int rc = 0;
1450 int connected = 0;
1451 __be16 orig_port = 0;
1452
fb8c4b14 1453 if (*csocket == NULL) {
50c2f753
SF
1454 rc = sock_create_kern(PF_INET, SOCK_STREAM,
1455 IPPROTO_TCP, csocket);
1da177e4 1456 if (rc < 0) {
50c2f753 1457 cERROR(1, ("Error %d creating socket", rc));
1da177e4
LT
1458 *csocket = NULL;
1459 return rc;
1460 } else {
1461 /* BB other socket options to set KEEPALIVE, NODELAY? */
467a8f8d 1462 cFYI(1, ("Socket created"));
50c2f753 1463 (*csocket)->sk->sk_allocation = GFP_NOFS;
1da177e4
LT
1464 }
1465 }
1466
1467 psin_server->sin_family = AF_INET;
fb8c4b14 1468 if (psin_server->sin_port) { /* user overrode default port */
1da177e4
LT
1469 rc = (*csocket)->ops->connect(*csocket,
1470 (struct sockaddr *) psin_server,
6345a3a8 1471 sizeof(struct sockaddr_in), 0);
1da177e4
LT
1472 if (rc >= 0)
1473 connected = 1;
50c2f753 1474 }
1da177e4 1475
fb8c4b14 1476 if (!connected) {
50c2f753 1477 /* save original port so we can retry user specified port
1da177e4
LT
1478 later if fall back ports fail this time */
1479 orig_port = psin_server->sin_port;
1480
1481 /* do not retry on the same port we just failed on */
fb8c4b14 1482 if (psin_server->sin_port != htons(CIFS_PORT)) {
1da177e4
LT
1483 psin_server->sin_port = htons(CIFS_PORT);
1484
1485 rc = (*csocket)->ops->connect(*csocket,
1486 (struct sockaddr *) psin_server,
6345a3a8 1487 sizeof(struct sockaddr_in), 0);
1da177e4
LT
1488 if (rc >= 0)
1489 connected = 1;
1490 }
1491 }
1492 if (!connected) {
1493 psin_server->sin_port = htons(RFC1001_PORT);
1494 rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
50c2f753 1495 psin_server,
6345a3a8 1496 sizeof(struct sockaddr_in), 0);
50c2f753 1497 if (rc >= 0)
1da177e4
LT
1498 connected = 1;
1499 }
1500
1501 /* give up here - unless we want to retry on different
1502 protocol families some day */
1503 if (!connected) {
fb8c4b14 1504 if (orig_port)
1da177e4 1505 psin_server->sin_port = orig_port;
50c2f753 1506 cFYI(1, ("Error %d connecting to server via ipv4", rc));
1da177e4
LT
1507 sock_release(*csocket);
1508 *csocket = NULL;
1509 return rc;
1510 }
50c2f753
SF
1511 /* Eventually check for other socket options to change from
1512 the default. sock_setsockopt not used because it expects
1da177e4 1513 user space buffer */
50c2f753
SF
1514 cFYI(1, ("sndbuf %d rcvbuf %d rcvtimeo 0x%lx",
1515 (*csocket)->sk->sk_sndbuf,
b387eaeb 1516 (*csocket)->sk->sk_rcvbuf, (*csocket)->sk->sk_rcvtimeo));
1da177e4 1517 (*csocket)->sk->sk_rcvtimeo = 7 * HZ;
b387eaeb 1518 /* make the bufsizes depend on wsize/rsize and max requests */
fb8c4b14 1519 if ((*csocket)->sk->sk_sndbuf < (200 * 1024))
b387eaeb 1520 (*csocket)->sk->sk_sndbuf = 200 * 1024;
fb8c4b14 1521 if ((*csocket)->sk->sk_rcvbuf < (140 * 1024))
b387eaeb 1522 (*csocket)->sk->sk_rcvbuf = 140 * 1024;
1da177e4
LT
1523
1524 /* send RFC1001 sessinit */
fb8c4b14 1525 if (psin_server->sin_port == htons(RFC1001_PORT)) {
1da177e4 1526 /* some servers require RFC1001 sessinit before sending
50c2f753 1527 negprot - BB check reconnection in case where second
1da177e4 1528 sessinit is sent but no second negprot */
50c2f753
SF
1529 struct rfc1002_session_packet *ses_init_buf;
1530 struct smb_hdr *smb_buf;
1531 ses_init_buf = kzalloc(sizeof(struct rfc1002_session_packet),
1532 GFP_KERNEL);
fb8c4b14 1533 if (ses_init_buf) {
1da177e4 1534 ses_init_buf->trailer.session_req.called_len = 32;
fb8c4b14 1535 if (target_name && (target_name[0] != 0)) {
a10faeb2
SF
1536 rfc1002mangle(ses_init_buf->trailer.session_req.called_name,
1537 target_name, 16);
1538 } else {
1539 rfc1002mangle(ses_init_buf->trailer.session_req.called_name,
50c2f753 1540 DEFAULT_CIFS_CALLED_NAME, 16);
a10faeb2
SF
1541 }
1542
1da177e4
LT
1543 ses_init_buf->trailer.session_req.calling_len = 32;
1544 /* calling name ends in null (byte 16) from old smb
1545 convention. */
50c2f753 1546 if (netbios_name && (netbios_name[0] != 0)) {
1da177e4 1547 rfc1002mangle(ses_init_buf->trailer.session_req.calling_name,
50c2f753 1548 netbios_name, 16);
1da177e4
LT
1549 } else {
1550 rfc1002mangle(ses_init_buf->trailer.session_req.calling_name,
50c2f753 1551 "LINUX_CIFS_CLNT", 16);
1da177e4
LT
1552 }
1553 ses_init_buf->trailer.session_req.scope1 = 0;
1554 ses_init_buf->trailer.session_req.scope2 = 0;
1555 smb_buf = (struct smb_hdr *)ses_init_buf;
1556 /* sizeof RFC1002_SESSION_REQUEST with no scope */
1557 smb_buf->smb_buf_length = 0x81000044;
1558 rc = smb_send(*csocket, smb_buf, 0x44,
1559 (struct sockaddr *)psin_server);
1560 kfree(ses_init_buf);
50c2f753 1561 msleep(1); /* RFC1001 layer in at least one server
083d3a2c
SF
1562 requires very short break before negprot
1563 presumably because not expecting negprot
1564 to follow so fast. This is a simple
50c2f753 1565 solution that works without
083d3a2c
SF
1566 complicating the code and causes no
1567 significant slowing down on mount
1568 for everyone else */
1da177e4 1569 }
50c2f753 1570 /* else the negprot may still work without this
1da177e4 1571 even though malloc failed */
50c2f753 1572
1da177e4 1573 }
50c2f753 1574
1da177e4
LT
1575 return rc;
1576}
1577
1578static int
1579ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket)
1580{
1581 int rc = 0;
1582 int connected = 0;
1583 __be16 orig_port = 0;
1584
fb8c4b14 1585 if (*csocket == NULL) {
50c2f753
SF
1586 rc = sock_create_kern(PF_INET6, SOCK_STREAM,
1587 IPPROTO_TCP, csocket);
1da177e4 1588 if (rc < 0) {
50c2f753 1589 cERROR(1, ("Error %d creating ipv6 socket", rc));
1da177e4
LT
1590 *csocket = NULL;
1591 return rc;
1592 } else {
1593 /* BB other socket options to set KEEPALIVE, NODELAY? */
fb8c4b14 1594 cFYI(1, ("ipv6 Socket created"));
1da177e4
LT
1595 (*csocket)->sk->sk_allocation = GFP_NOFS;
1596 }
1597 }
1598
1599 psin_server->sin6_family = AF_INET6;
1600
fb8c4b14 1601 if (psin_server->sin6_port) { /* user overrode default port */
1da177e4
LT
1602 rc = (*csocket)->ops->connect(*csocket,
1603 (struct sockaddr *) psin_server,
6345a3a8 1604 sizeof(struct sockaddr_in6), 0);
1da177e4
LT
1605 if (rc >= 0)
1606 connected = 1;
50c2f753 1607 }
1da177e4 1608
fb8c4b14 1609 if (!connected) {
50c2f753 1610 /* save original port so we can retry user specified port
1da177e4
LT
1611 later if fall back ports fail this time */
1612
1613 orig_port = psin_server->sin6_port;
1614 /* do not retry on the same port we just failed on */
fb8c4b14 1615 if (psin_server->sin6_port != htons(CIFS_PORT)) {
1da177e4
LT
1616 psin_server->sin6_port = htons(CIFS_PORT);
1617
1618 rc = (*csocket)->ops->connect(*csocket,
1619 (struct sockaddr *) psin_server,
6345a3a8 1620 sizeof(struct sockaddr_in6), 0);
1da177e4
LT
1621 if (rc >= 0)
1622 connected = 1;
1623 }
1624 }
1625 if (!connected) {
1626 psin_server->sin6_port = htons(RFC1001_PORT);
1627 rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
6345a3a8 1628 psin_server, sizeof(struct sockaddr_in6), 0);
50c2f753 1629 if (rc >= 0)
1da177e4
LT
1630 connected = 1;
1631 }
1632
1633 /* give up here - unless we want to retry on different
1634 protocol families some day */
1635 if (!connected) {
fb8c4b14 1636 if (orig_port)
1da177e4 1637 psin_server->sin6_port = orig_port;
50c2f753 1638 cFYI(1, ("Error %d connecting to server via ipv6", rc));
1da177e4
LT
1639 sock_release(*csocket);
1640 *csocket = NULL;
1641 return rc;
1642 }
50c2f753
SF
1643 /* Eventually check for other socket options to change from
1644 the default. sock_setsockopt not used because it expects
1da177e4
LT
1645 user space buffer */
1646 (*csocket)->sk->sk_rcvtimeo = 7 * HZ;
50c2f753 1647
1da177e4
LT
1648 return rc;
1649}
1650
50c2f753
SF
1651void reset_cifs_unix_caps(int xid, struct cifsTconInfo *tcon,
1652 struct super_block *sb, struct smb_vol *vol_info)
8af18971
SF
1653{
1654 /* if we are reconnecting then should we check to see if
1655 * any requested capabilities changed locally e.g. via
1656 * remount but we can not do much about it here
1657 * if they have (even if we could detect it by the following)
1658 * Perhaps we could add a backpointer to array of sb from tcon
1659 * or if we change to make all sb to same share the same
1660 * sb as NFS - then we only have one backpointer to sb.
1661 * What if we wanted to mount the server share twice once with
1662 * and once without posixacls or posix paths? */
1663 __u64 saved_cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
50c2f753 1664
c18c842b
SF
1665 if (vol_info && vol_info->no_linux_ext) {
1666 tcon->fsUnixInfo.Capability = 0;
1667 tcon->unix_ext = 0; /* Unix Extensions disabled */
1668 cFYI(1, ("Linux protocol extensions disabled"));
1669 return;
1670 } else if (vol_info)
1671 tcon->unix_ext = 1; /* Unix Extensions supported */
1672
1673 if (tcon->unix_ext == 0) {
1674 cFYI(1, ("Unix extensions disabled so not set on reconnect"));
1675 return;
1676 }
50c2f753 1677
fb8c4b14 1678 if (!CIFSSMBQFSUnixInfo(xid, tcon)) {
8af18971 1679 __u64 cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
50c2f753 1680
8af18971
SF
1681 /* check for reconnect case in which we do not
1682 want to change the mount behavior if we can avoid it */
fb8c4b14 1683 if (vol_info == NULL) {
50c2f753 1684 /* turn off POSIX ACL and PATHNAMES if not set
8af18971
SF
1685 originally at mount time */
1686 if ((saved_cap & CIFS_UNIX_POSIX_ACL_CAP) == 0)
1687 cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
1688 if ((saved_cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0)
1689 cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
8af18971 1690 }
50c2f753 1691
8af18971 1692 cap &= CIFS_UNIX_CAP_MASK;
75865f8c 1693 if (vol_info && vol_info->no_psx_acl)
8af18971 1694 cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
75865f8c 1695 else if (CIFS_UNIX_POSIX_ACL_CAP & cap) {
fb8c4b14
SF
1696 cFYI(1, ("negotiated posix acl support"));
1697 if (sb)
8af18971
SF
1698 sb->s_flags |= MS_POSIXACL;
1699 }
1700
75865f8c 1701 if (vol_info && vol_info->posix_paths == 0)
8af18971 1702 cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
75865f8c 1703 else if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
fb8c4b14 1704 cFYI(1, ("negotiate posix pathnames"));
75865f8c 1705 if (sb)
50c2f753 1706 CIFS_SB(sb)->mnt_cifs_flags |=
8af18971
SF
1707 CIFS_MOUNT_POSIX_PATHS;
1708 }
50c2f753 1709
984acfe1
SF
1710 /* We might be setting the path sep back to a different
1711 form if we are reconnecting and the server switched its
50c2f753 1712 posix path capability for this share */
75865f8c 1713 if (sb && (CIFS_SB(sb)->prepathlen > 0))
984acfe1 1714 CIFS_SB(sb)->prepath[0] = CIFS_DIR_SEP(CIFS_SB(sb));
75865f8c
SF
1715
1716 if (sb && (CIFS_SB(sb)->rsize > 127 * 1024)) {
1717 if ((cap & CIFS_UNIX_LARGE_READ_CAP) == 0) {
1718 CIFS_SB(sb)->rsize = 127 * 1024;
1719#ifdef CONFIG_CIFS_DEBUG2
fb8c4b14 1720 cFYI(1, ("larger reads not supported by srv"));
75865f8c
SF
1721#endif
1722 }
1723 }
50c2f753
SF
1724
1725
1726 cFYI(1, ("Negotiate caps 0x%x", (int)cap));
8af18971 1727#ifdef CONFIG_CIFS_DEBUG2
75865f8c 1728 if (cap & CIFS_UNIX_FCNTL_CAP)
fb8c4b14 1729 cFYI(1, ("FCNTL cap"));
75865f8c 1730 if (cap & CIFS_UNIX_EXTATTR_CAP)
fb8c4b14 1731 cFYI(1, ("EXTATTR cap"));
75865f8c 1732 if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
fb8c4b14 1733 cFYI(1, ("POSIX path cap"));
75865f8c 1734 if (cap & CIFS_UNIX_XATTR_CAP)
fb8c4b14 1735 cFYI(1, ("XATTR cap"));
75865f8c 1736 if (cap & CIFS_UNIX_POSIX_ACL_CAP)
fb8c4b14 1737 cFYI(1, ("POSIX ACL cap"));
75865f8c 1738 if (cap & CIFS_UNIX_LARGE_READ_CAP)
fb8c4b14 1739 cFYI(1, ("very large read cap"));
75865f8c 1740 if (cap & CIFS_UNIX_LARGE_WRITE_CAP)
fb8c4b14 1741 cFYI(1, ("very large write cap"));
8af18971
SF
1742#endif /* CIFS_DEBUG2 */
1743 if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) {
442aa310 1744 if (vol_info == NULL) {
5a44b319 1745 cFYI(1, ("resetting capabilities failed"));
442aa310 1746 } else
5a44b319
SF
1747 cERROR(1, ("Negotiating Unix capabilities "
1748 "with the server failed. Consider "
1749 "mounting with the Unix Extensions\n"
1750 "disabled, if problems are found, "
1751 "by specifying the nounix mount "
2224f4e5 1752 "option."));
5a44b319 1753
8af18971
SF
1754 }
1755 }
1756}
1757
1da177e4
LT
1758int
1759cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1760 char *mount_data, const char *devname)
1761{
1762 int rc = 0;
1763 int xid;
1764 int address_type = AF_INET;
1765 struct socket *csocket = NULL;
1766 struct sockaddr_in sin_server;
1767 struct sockaddr_in6 sin_server6;
1768 struct smb_vol volume_info;
1769 struct cifsSesInfo *pSesInfo = NULL;
1770 struct cifsSesInfo *existingCifsSes = NULL;
1771 struct cifsTconInfo *tcon = NULL;
1772 struct TCP_Server_Info *srvTcp = NULL;
1773
1774 xid = GetXid();
1775
1776/* cFYI(1, ("Entering cifs_mount. Xid: %d with: %s", xid, mount_data)); */
50c2f753
SF
1777
1778 memset(&volume_info, 0, sizeof(struct smb_vol));
1da177e4 1779 if (cifs_parse_mount_options(mount_data, devname, &volume_info)) {
f99d49ad
JJ
1780 kfree(volume_info.UNC);
1781 kfree(volume_info.password);
2fe87f02 1782 kfree(volume_info.prepath);
1da177e4
LT
1783 FreeXid(xid);
1784 return -EINVAL;
1785 }
1786
8426c39c 1787 if (volume_info.nullauth) {
fb8c4b14 1788 cFYI(1, ("null user"));
8426c39c
JL
1789 volume_info.username = NULL;
1790 } else if (volume_info.username) {
1da177e4 1791 /* BB fixme parse for domain name here */
467a8f8d 1792 cFYI(1, ("Username: %s", volume_info.username));
1da177e4 1793 } else {
bf820679 1794 cifserror("No username specified");
50c2f753
SF
1795 /* In userspace mount helper we can get user name from alternate
1796 locations such as env variables and files on disk */
f99d49ad
JJ
1797 kfree(volume_info.UNC);
1798 kfree(volume_info.password);
2fe87f02 1799 kfree(volume_info.prepath);
1da177e4
LT
1800 FreeXid(xid);
1801 return -EINVAL;
1802 }
1803
1804 if (volume_info.UNCip && volume_info.UNC) {
50c2f753
SF
1805 rc = cifs_inet_pton(AF_INET, volume_info.UNCip,
1806 &sin_server.sin_addr.s_addr);
1da177e4 1807
fb8c4b14 1808 if (rc <= 0) {
1da177e4 1809 /* not ipv4 address, try ipv6 */
50c2f753
SF
1810 rc = cifs_inet_pton(AF_INET6, volume_info.UNCip,
1811 &sin_server6.sin6_addr.in6_u);
fb8c4b14 1812 if (rc > 0)
1da177e4
LT
1813 address_type = AF_INET6;
1814 } else {
1815 address_type = AF_INET;
1816 }
50c2f753 1817
fb8c4b14 1818 if (rc <= 0) {
1da177e4 1819 /* we failed translating address */
f99d49ad
JJ
1820 kfree(volume_info.UNC);
1821 kfree(volume_info.password);
2fe87f02 1822 kfree(volume_info.prepath);
1da177e4
LT
1823 FreeXid(xid);
1824 return -EINVAL;
1825 }
1826
1827 cFYI(1, ("UNC: %s ip: %s", volume_info.UNC, volume_info.UNCip));
1828 /* success */
1829 rc = 0;
50c2f753
SF
1830 } else if (volume_info.UNCip) {
1831 /* BB using ip addr as server name to connect to the
1832 DFS root below */
1833 cERROR(1, ("Connecting to DFS root not implemented yet"));
f99d49ad
JJ
1834 kfree(volume_info.UNC);
1835 kfree(volume_info.password);
2fe87f02 1836 kfree(volume_info.prepath);
1da177e4
LT
1837 FreeXid(xid);
1838 return -EINVAL;
1839 } else /* which servers DFS root would we conect to */ {
1840 cERROR(1,
50c2f753
SF
1841 ("CIFS mount error: No UNC path (e.g. -o "
1842 "unc=//192.168.1.100/public) specified"));
f99d49ad
JJ
1843 kfree(volume_info.UNC);
1844 kfree(volume_info.password);
2fe87f02 1845 kfree(volume_info.prepath);
1da177e4
LT
1846 FreeXid(xid);
1847 return -EINVAL;
1848 }
1849
1850 /* this is needed for ASCII cp to Unicode converts */
fb8c4b14 1851 if (volume_info.iocharset == NULL) {
1da177e4
LT
1852 cifs_sb->local_nls = load_nls_default();
1853 /* load_nls_default can not return null */
1854 } else {
1855 cifs_sb->local_nls = load_nls(volume_info.iocharset);
fb8c4b14 1856 if (cifs_sb->local_nls == NULL) {
50c2f753
SF
1857 cERROR(1, ("CIFS mount error: iocharset %s not found",
1858 volume_info.iocharset));
f99d49ad
JJ
1859 kfree(volume_info.UNC);
1860 kfree(volume_info.password);
2fe87f02 1861 kfree(volume_info.prepath);
1da177e4
LT
1862 FreeXid(xid);
1863 return -ELIBACC;
1864 }
1865 }
1866
fb8c4b14 1867 if (address_type == AF_INET)
1da177e4
LT
1868 existingCifsSes = cifs_find_tcp_session(&sin_server.sin_addr,
1869 NULL /* no ipv6 addr */,
1870 volume_info.username, &srvTcp);
fb8c4b14
SF
1871 else if (address_type == AF_INET6) {
1872 cFYI(1, ("looking for ipv6 address"));
1da177e4
LT
1873 existingCifsSes = cifs_find_tcp_session(NULL /* no ipv4 addr */,
1874 &sin_server6.sin6_addr,
1875 volume_info.username, &srvTcp);
5858ae44 1876 } else {
f99d49ad
JJ
1877 kfree(volume_info.UNC);
1878 kfree(volume_info.password);
2fe87f02 1879 kfree(volume_info.prepath);
1da177e4
LT
1880 FreeXid(xid);
1881 return -EINVAL;
1882 }
1883
1da177e4 1884 if (srvTcp) {
50c2f753 1885 cFYI(1, ("Existing tcp session with server found"));
1da177e4 1886 } else { /* create socket */
4523cc30 1887 if (volume_info.port)
1da177e4
LT
1888 sin_server.sin_port = htons(volume_info.port);
1889 else
1890 sin_server.sin_port = 0;
5858ae44 1891 if (address_type == AF_INET6) {
fb8c4b14 1892 cFYI(1, ("attempting ipv6 connect"));
5858ae44
SF
1893 /* BB should we allow ipv6 on port 139? */
1894 /* other OS never observed in Wild doing 139 with v6 */
50c2f753
SF
1895 rc = ipv6_connect(&sin_server6, &csocket);
1896 } else
1897 rc = ipv4_connect(&sin_server, &csocket,
a10faeb2
SF
1898 volume_info.source_rfc1001_name,
1899 volume_info.target_rfc1001_name);
1da177e4 1900 if (rc < 0) {
50c2f753
SF
1901 cERROR(1, ("Error connecting to IPv4 socket. "
1902 "Aborting operation"));
4523cc30 1903 if (csocket != NULL)
1da177e4 1904 sock_release(csocket);
f99d49ad
JJ
1905 kfree(volume_info.UNC);
1906 kfree(volume_info.password);
2fe87f02 1907 kfree(volume_info.prepath);
1da177e4
LT
1908 FreeXid(xid);
1909 return rc;
1910 }
1911
a8a11d39
MK
1912 srvTcp = kzalloc(sizeof(struct TCP_Server_Info), GFP_KERNEL);
1913 if (!srvTcp) {
1da177e4
LT
1914 rc = -ENOMEM;
1915 sock_release(csocket);
f99d49ad
JJ
1916 kfree(volume_info.UNC);
1917 kfree(volume_info.password);
2fe87f02 1918 kfree(volume_info.prepath);
1da177e4
LT
1919 FreeXid(xid);
1920 return rc;
1921 } else {
50c2f753 1922 memcpy(&srvTcp->addr.sockAddr, &sin_server,
6345a3a8 1923 sizeof(struct sockaddr_in));
50c2f753 1924 atomic_set(&srvTcp->inFlight, 0);
1da177e4
LT
1925 /* BB Add code for ipv6 case too */
1926 srvTcp->ssocket = csocket;
1927 srvTcp->protocolType = IPV4;
1928 init_waitqueue_head(&srvTcp->response_q);
1929 init_waitqueue_head(&srvTcp->request_q);
1930 INIT_LIST_HEAD(&srvTcp->pending_mid_q);
1931 /* at this point we are the only ones with the pointer
1932 to the struct since the kernel thread not created yet
1933 so no need to spinlock this init of tcpStatus */
1934 srvTcp->tcpStatus = CifsNew;
1935 init_MUTEX(&srvTcp->tcpSem);
aaf737ad 1936 srvTcp->tsk = kthread_run((void *)(void *)cifs_demultiplex_thread, srvTcp, "cifsd");
4523cc30 1937 if ( IS_ERR(srvTcp->tsk) ) {
aaf737ad 1938 rc = PTR_ERR(srvTcp->tsk);
50c2f753 1939 cERROR(1, ("error %d create cifsd thread", rc));
aaf737ad 1940 srvTcp->tsk = NULL;
1da177e4 1941 sock_release(csocket);
f99d49ad
JJ
1942 kfree(volume_info.UNC);
1943 kfree(volume_info.password);
2fe87f02 1944 kfree(volume_info.prepath);
1da177e4
LT
1945 FreeXid(xid);
1946 return rc;
f191401f
SF
1947 }
1948 wait_for_completion(&cifsd_complete);
1949 rc = 0;
50c2f753
SF
1950 memcpy(srvTcp->workstation_RFC1001_name,
1951 volume_info.source_rfc1001_name, 16);
1952 memcpy(srvTcp->server_RFC1001_name,
1953 volume_info.target_rfc1001_name, 16);
ad009ac9 1954 srvTcp->sequence_number = 0;
1da177e4
LT
1955 }
1956 }
1957
1958 if (existingCifsSes) {
1959 pSesInfo = existingCifsSes;
bf820679 1960 cFYI(1, ("Existing smb sess found"));
f99d49ad 1961 kfree(volume_info.password);
1da177e4
LT
1962 /* volume_info.UNC freed at end of function */
1963 } else if (!rc) {
bf820679 1964 cFYI(1, ("Existing smb sess not found"));
1da177e4
LT
1965 pSesInfo = sesInfoAlloc();
1966 if (pSesInfo == NULL)
1967 rc = -ENOMEM;
1968 else {
1969 pSesInfo->server = srvTcp;
1970 sprintf(pSesInfo->serverName, "%u.%u.%u.%u",
1971 NIPQUAD(sin_server.sin_addr.s_addr));
1972 }
1973
50c2f753
SF
1974 if (!rc) {
1975 /* volume_info.password freed at unmount */
1da177e4
LT
1976 if (volume_info.password)
1977 pSesInfo->password = volume_info.password;
1978 if (volume_info.username)
1979 strncpy(pSesInfo->userName,
50c2f753
SF
1980 volume_info.username,
1981 MAX_USERNAME_SIZE);
3979877e
SF
1982 if (volume_info.domainname) {
1983 int len = strlen(volume_info.domainname);
50c2f753 1984 pSesInfo->domainName =
3979877e 1985 kmalloc(len + 1, GFP_KERNEL);
4523cc30 1986 if (pSesInfo->domainName)
3979877e
SF
1987 strcpy(pSesInfo->domainName,
1988 volume_info.domainname);
1989 }
1da177e4 1990 pSesInfo->linux_uid = volume_info.linux_uid;
750d1151 1991 pSesInfo->overrideSecFlg = volume_info.secFlg;
1da177e4 1992 down(&pSesInfo->sesSem);
189acaae 1993 /* BB FIXME need to pass vol->secFlgs BB */
50c2f753
SF
1994 rc = cifs_setup_session(xid, pSesInfo,
1995 cifs_sb->local_nls);
1da177e4 1996 up(&pSesInfo->sesSem);
4523cc30 1997 if (!rc)
1da177e4
LT
1998 atomic_inc(&srvTcp->socketUseCount);
1999 } else
f99d49ad 2000 kfree(volume_info.password);
1da177e4 2001 }
50c2f753 2002
1da177e4
LT
2003 /* search for existing tcon to this server share */
2004 if (!rc) {
4523cc30 2005 if (volume_info.rsize > CIFSMaxBufSize) {
50c2f753 2006 cERROR(1, ("rsize %d too large, using MaxBufSize",
0ae0efad
SF
2007 volume_info.rsize));
2008 cifs_sb->rsize = CIFSMaxBufSize;
75865f8c
SF
2009 } else if ((volume_info.rsize) &&
2010 (volume_info.rsize <= CIFSMaxBufSize))
1da177e4 2011 cifs_sb->rsize = volume_info.rsize;
0ae0efad
SF
2012 else /* default */
2013 cifs_sb->rsize = CIFSMaxBufSize;
2014
4523cc30 2015 if (volume_info.wsize > PAGEVEC_SIZE * PAGE_CACHE_SIZE) {
50c2f753 2016 cERROR(1, ("wsize %d too large, using 4096 instead",
0ae0efad
SF
2017 volume_info.wsize));
2018 cifs_sb->wsize = 4096;
4523cc30 2019 } else if (volume_info.wsize)
1da177e4
LT
2020 cifs_sb->wsize = volume_info.wsize;
2021 else
50c2f753 2022 cifs_sb->wsize =
1877c9ea
SF
2023 min_t(const int, PAGEVEC_SIZE * PAGE_CACHE_SIZE,
2024 127*1024);
17cbbafe 2025 /* old default of CIFSMaxBufSize was too small now
50c2f753 2026 that SMB Write2 can send multiple pages in kvec.
17cbbafe
SF
2027 RFC1001 does not describe what happens when frame
2028 bigger than 128K is sent so use that as max in
2029 conjunction with 52K kvec constraint on arch with 4K
2030 page size */
2031
4523cc30 2032 if (cifs_sb->rsize < 2048) {
50c2f753 2033 cifs_sb->rsize = 2048;
6cec2aed 2034 /* Windows ME may prefer this */
467a8f8d 2035 cFYI(1, ("readsize set to minimum: 2048"));
1da177e4 2036 }
2fe87f02
SF
2037 /* calculate prepath */
2038 cifs_sb->prepath = volume_info.prepath;
4523cc30 2039 if (cifs_sb->prepath) {
2fe87f02
SF
2040 cifs_sb->prepathlen = strlen(cifs_sb->prepath);
2041 cifs_sb->prepath[0] = CIFS_DIR_SEP(cifs_sb);
2042 volume_info.prepath = NULL;
50c2f753 2043 } else
2fe87f02 2044 cifs_sb->prepathlen = 0;
1da177e4
LT
2045 cifs_sb->mnt_uid = volume_info.linux_uid;
2046 cifs_sb->mnt_gid = volume_info.linux_gid;
2047 cifs_sb->mnt_file_mode = volume_info.file_mode;
2048 cifs_sb->mnt_dir_mode = volume_info.dir_mode;
467a8f8d
SF
2049 cFYI(1, ("file mode: 0x%x dir mode: 0x%x",
2050 cifs_sb->mnt_file_mode, cifs_sb->mnt_dir_mode));
1da177e4 2051
4523cc30 2052 if (volume_info.noperm)
1da177e4 2053 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
4523cc30 2054 if (volume_info.setuids)
1da177e4 2055 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
4523cc30 2056 if (volume_info.server_ino)
1da177e4 2057 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
4523cc30 2058 if (volume_info.remap)
6a0b4824 2059 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
4523cc30 2060 if (volume_info.no_xattr)
1da177e4 2061 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
4523cc30 2062 if (volume_info.sfu_emul)
d7245c2c 2063 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL;
4523cc30 2064 if (volume_info.nobrl)
c46fa8ac 2065 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL;
4523cc30 2066 if (volume_info.cifs_acl)
0a4b92c0 2067 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL;
4523cc30
SF
2068 if (volume_info.override_uid)
2069 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_UID;
2070 if (volume_info.override_gid)
2071 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_GID;
2072 if (volume_info.direct_io) {
467a8f8d 2073 cFYI(1, ("mounting share using direct i/o"));
1da177e4
LT
2074 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
2075 }
2076
2077 tcon =
2078 find_unc(sin_server.sin_addr.s_addr, volume_info.UNC,
2079 volume_info.username);
2080 if (tcon) {
bf820679 2081 cFYI(1, ("Found match on UNC path"));
1da177e4
LT
2082 /* we can have only one retry value for a connection
2083 to a share so for resources mounted more than once
50c2f753 2084 to the same server share the last value passed in
1da177e4
LT
2085 for the retry flag is used */
2086 tcon->retry = volume_info.retry;
d3485d37 2087 tcon->nocase = volume_info.nocase;
1da177e4
LT
2088 } else {
2089 tcon = tconInfoAlloc();
2090 if (tcon == NULL)
2091 rc = -ENOMEM;
2092 else {
50c2f753 2093 /* check for null share name ie connecting to
8af18971 2094 * dfs root */
1da177e4 2095
50c2f753 2096 /* BB check if this works for exactly length
8af18971 2097 * three strings */
1da177e4
LT
2098 if ((strchr(volume_info.UNC + 3, '\\') == NULL)
2099 && (strchr(volume_info.UNC + 3, '/') ==
2100 NULL)) {
737b758c 2101 rc = connect_to_dfs_path(xid, pSesInfo,
8af18971 2102 "", cifs_sb->local_nls,
50c2f753 2103 cifs_sb->mnt_cifs_flags &
8af18971 2104 CIFS_MOUNT_MAP_SPECIAL_CHR);
f99d49ad 2105 kfree(volume_info.UNC);
1da177e4
LT
2106 FreeXid(xid);
2107 return -ENODEV;
2108 } else {
8af18971
SF
2109 /* BB Do we need to wrap sesSem around
2110 * this TCon call and Unix SetFS as
2111 * we do on SessSetup and reconnect? */
50c2f753 2112 rc = CIFSTCon(xid, pSesInfo,
1da177e4
LT
2113 volume_info.UNC,
2114 tcon, cifs_sb->local_nls);
2115 cFYI(1, ("CIFS Tcon rc = %d", rc));
2116 }
2117 if (!rc) {
2118 atomic_inc(&pSesInfo->inUse);
2119 tcon->retry = volume_info.retry;
d3485d37 2120 tcon->nocase = volume_info.nocase;
1da177e4
LT
2121 }
2122 }
2123 }
2124 }
4523cc30 2125 if (pSesInfo) {
1da177e4
LT
2126 if (pSesInfo->capabilities & CAP_LARGE_FILES) {
2127 sb->s_maxbytes = (u64) 1 << 63;
2128 } else
2129 sb->s_maxbytes = (u64) 1 << 31; /* 2 GB */
2130 }
2131
8af18971 2132 /* BB FIXME fix time_gran to be larger for LANMAN sessions */
1da177e4
LT
2133 sb->s_time_gran = 100;
2134
2135/* on error free sesinfo and tcon struct if needed */
2136 if (rc) {
2137 /* if session setup failed, use count is zero but
2138 we still need to free cifsd thread */
4523cc30 2139 if (atomic_read(&srvTcp->socketUseCount) == 0) {
1da177e4
LT
2140 spin_lock(&GlobalMid_Lock);
2141 srvTcp->tcpStatus = CifsExiting;
2142 spin_unlock(&GlobalMid_Lock);
4523cc30 2143 if (srvTcp->tsk) {
28356a16
SF
2144 struct task_struct *tsk;
2145 /* If we could verify that kthread_stop would
2146 always wake up processes blocked in
2147 tcp in recv_mesg then we could remove the
2148 send_sig call */
50c2f753 2149 force_sig(SIGKILL, srvTcp->tsk);
28356a16 2150 tsk = srvTcp->tsk;
fb8c4b14 2151 if (tsk)
f7f7c31c 2152 kthread_stop(tsk);
f191401f 2153 }
1da177e4
LT
2154 }
2155 /* If find_unc succeeded then rc == 0 so we can not end */
2156 if (tcon) /* up accidently freeing someone elses tcon struct */
2157 tconInfoFree(tcon);
2158 if (existingCifsSes == NULL) {
2159 if (pSesInfo) {
50c2f753 2160 if ((pSesInfo->server) &&
1da177e4
LT
2161 (pSesInfo->status == CifsGood)) {
2162 int temp_rc;
2163 temp_rc = CIFSSMBLogoff(xid, pSesInfo);
2164 /* if the socketUseCount is now zero */
4523cc30 2165 if ((temp_rc == -ESHUTDOWN) &&
50c2f753 2166 (pSesInfo->server) &&
5d9c7206 2167 (pSesInfo->server->tsk)) {
28356a16 2168 struct task_struct *tsk;
5d9c7206
J
2169 force_sig(SIGKILL,
2170 pSesInfo->server->tsk);
28356a16 2171 tsk = pSesInfo->server->tsk;
f7f7c31c 2172 if (tsk)
28356a16 2173 kthread_stop(tsk);
f191401f 2174 }
a013689d 2175 } else {
1da177e4 2176 cFYI(1, ("No session or bad tcon"));
a013689d
SF
2177 if ((pSesInfo->server) &&
2178 (pSesInfo->server->tsk)) {
2179 struct task_struct *tsk;
2180 force_sig(SIGKILL,
2181 pSesInfo->server->tsk);
2182 tsk = pSesInfo->server->tsk;
2183 if (tsk)
2184 kthread_stop(tsk);
2185 }
2186 }
1da177e4
LT
2187 sesInfoFree(pSesInfo);
2188 /* pSesInfo = NULL; */
2189 }
2190 }
2191 } else {
2192 atomic_inc(&tcon->useCount);
2193 cifs_sb->tcon = tcon;
2194 tcon->ses = pSesInfo;
2195
82940a46 2196 /* do not care if following two calls succeed - informational */
7f8ed420
SF
2197 if (!tcon->ipc) {
2198 CIFSSMBQFSDeviceInfo(xid, tcon);
2199 CIFSSMBQFSAttributeInfo(xid, tcon);
2200 }
50c2f753 2201
8af18971
SF
2202 /* tell server which Unix caps we support */
2203 if (tcon->ses->capabilities & CAP_UNIX)
c18c842b
SF
2204 /* reset of caps checks mount to see if unix extensions
2205 disabled for just this mount */
8af18971 2206 reset_cifs_unix_caps(xid, tcon, sb, &volume_info);
c18c842b
SF
2207 else
2208 tcon->unix_ext = 0; /* server does not support them */
2209
2210 if ((tcon->unix_ext == 0) && (cifs_sb->rsize > (1024 * 127))) {
75865f8c
SF
2211 cifs_sb->rsize = 1024 * 127;
2212#ifdef CONFIG_CIFS_DEBUG2
c18c842b 2213 cFYI(1, ("no very large read support, rsize now 127K"));
75865f8c 2214#endif
75865f8c 2215 }
3e84469d
SF
2216 if (!(tcon->ses->capabilities & CAP_LARGE_WRITE_X))
2217 cifs_sb->wsize = min(cifs_sb->wsize,
2218 (tcon->ses->server->maxBuf -
2219 MAX_CIFS_HDR_SIZE));
0ae0efad 2220 if (!(tcon->ses->capabilities & CAP_LARGE_READ_X))
50c2f753
SF
2221 cifs_sb->rsize = min(cifs_sb->rsize,
2222 (tcon->ses->server->maxBuf -
2223 MAX_CIFS_HDR_SIZE));
1da177e4
LT
2224 }
2225
2226 /* volume_info.password is freed above when existing session found
2227 (in which case it is not needed anymore) but when new sesion is created
2228 the password ptr is put in the new session structure (in which case the
2229 password will be freed at unmount time) */
f99d49ad 2230 kfree(volume_info.UNC);
2fe87f02 2231 kfree(volume_info.prepath);
1da177e4
LT
2232 FreeXid(xid);
2233 return rc;
2234}
2235
2236static int
2237CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
7c7b25bc 2238 char session_key[CIFS_SESS_KEY_SIZE],
1da177e4
LT
2239 const struct nls_table *nls_codepage)
2240{
2241 struct smb_hdr *smb_buffer;
2242 struct smb_hdr *smb_buffer_response;
2243 SESSION_SETUP_ANDX *pSMB;
2244 SESSION_SETUP_ANDX *pSMBr;
2245 char *bcc_ptr;
2246 char *user;
2247 char *domain;
2248 int rc = 0;
2249 int remaining_words = 0;
2250 int bytes_returned = 0;
2251 int len;
2252 __u32 capabilities;
2253 __u16 count;
2254
eeac8047 2255 cFYI(1, ("In sesssetup"));
4523cc30 2256 if (ses == NULL)
1da177e4
LT
2257 return -EINVAL;
2258 user = ses->userName;
2259 domain = ses->domainName;
2260 smb_buffer = cifs_buf_get();
2261 if (smb_buffer == NULL) {
2262 return -ENOMEM;
2263 }
2264 smb_buffer_response = smb_buffer;
2265 pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2266
2267 /* send SMBsessionSetup here */
2268 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2269 NULL /* no tCon exists yet */ , 13 /* wct */ );
2270
1982c344 2271 smb_buffer->Mid = GetNextMid(ses->server);
1da177e4
LT
2272 pSMB->req_no_secext.AndXCommand = 0xFF;
2273 pSMB->req_no_secext.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2274 pSMB->req_no_secext.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2275
50c2f753
SF
2276 if (ses->server->secMode &
2277 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
1da177e4
LT
2278 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2279
2280 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2281 CAP_LARGE_WRITE_X | CAP_LARGE_READ_X;
2282 if (ses->capabilities & CAP_UNICODE) {
2283 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2284 capabilities |= CAP_UNICODE;
2285 }
2286 if (ses->capabilities & CAP_STATUS32) {
2287 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2288 capabilities |= CAP_STATUS32;
2289 }
2290 if (ses->capabilities & CAP_DFS) {
2291 smb_buffer->Flags2 |= SMBFLG2_DFS;
2292 capabilities |= CAP_DFS;
2293 }
2294 pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
2295
50c2f753 2296 pSMB->req_no_secext.CaseInsensitivePasswordLength =
7c7b25bc 2297 cpu_to_le16(CIFS_SESS_KEY_SIZE);
1da177e4
LT
2298
2299 pSMB->req_no_secext.CaseSensitivePasswordLength =
7c7b25bc 2300 cpu_to_le16(CIFS_SESS_KEY_SIZE);
1da177e4 2301 bcc_ptr = pByteArea(smb_buffer);
7c7b25bc
SF
2302 memcpy(bcc_ptr, (char *) session_key, CIFS_SESS_KEY_SIZE);
2303 bcc_ptr += CIFS_SESS_KEY_SIZE;
2304 memcpy(bcc_ptr, (char *) session_key, CIFS_SESS_KEY_SIZE);
2305 bcc_ptr += CIFS_SESS_KEY_SIZE;
1da177e4
LT
2306
2307 if (ses->capabilities & CAP_UNICODE) {
2308 if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode */
2309 *bcc_ptr = 0;
2310 bcc_ptr++;
2311 }
4523cc30 2312 if (user == NULL)
3979877e 2313 bytes_returned = 0; /* skip null user */
50c2f753 2314 else
1da177e4 2315 bytes_returned =
50c2f753 2316 cifs_strtoUCS((__le16 *) bcc_ptr, user, 100,
1da177e4
LT
2317 nls_codepage);
2318 /* convert number of 16 bit words to bytes */
2319 bcc_ptr += 2 * bytes_returned;
2320 bcc_ptr += 2; /* trailing null */
2321 if (domain == NULL)
2322 bytes_returned =
e89dc920 2323 cifs_strtoUCS((__le16 *) bcc_ptr,
1da177e4
LT
2324 "CIFS_LINUX_DOM", 32, nls_codepage);
2325 else
2326 bytes_returned =
e89dc920 2327 cifs_strtoUCS((__le16 *) bcc_ptr, domain, 64,
1da177e4
LT
2328 nls_codepage);
2329 bcc_ptr += 2 * bytes_returned;
2330 bcc_ptr += 2;
2331 bytes_returned =
e89dc920 2332 cifs_strtoUCS((__le16 *) bcc_ptr, "Linux version ",
1da177e4
LT
2333 32, nls_codepage);
2334 bcc_ptr += 2 * bytes_returned;
2335 bytes_returned =
e9ff3990 2336 cifs_strtoUCS((__le16 *) bcc_ptr, utsname()->release,
1da177e4
LT
2337 32, nls_codepage);
2338 bcc_ptr += 2 * bytes_returned;
2339 bcc_ptr += 2;
2340 bytes_returned =
e89dc920 2341 cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
1da177e4
LT
2342 64, nls_codepage);
2343 bcc_ptr += 2 * bytes_returned;
2344 bcc_ptr += 2;
2345 } else {
50c2f753 2346 if (user != NULL) {
1da177e4
LT
2347 strncpy(bcc_ptr, user, 200);
2348 bcc_ptr += strnlen(user, 200);
2349 }
2350 *bcc_ptr = 0;
2351 bcc_ptr++;
2352 if (domain == NULL) {
2353 strcpy(bcc_ptr, "CIFS_LINUX_DOM");
2354 bcc_ptr += strlen("CIFS_LINUX_DOM") + 1;
2355 } else {
2356 strncpy(bcc_ptr, domain, 64);
2357 bcc_ptr += strnlen(domain, 64);
2358 *bcc_ptr = 0;
2359 bcc_ptr++;
2360 }
2361 strcpy(bcc_ptr, "Linux version ");
2362 bcc_ptr += strlen("Linux version ");
e9ff3990
SH
2363 strcpy(bcc_ptr, utsname()->release);
2364 bcc_ptr += strlen(utsname()->release) + 1;
1da177e4
LT
2365 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2366 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2367 }
2368 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2369 smb_buffer->smb_buf_length += count;
2370 pSMB->req_no_secext.ByteCount = cpu_to_le16(count);
2371
2372 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2373 &bytes_returned, 1);
2374 if (rc) {
2375/* rc = map_smb_to_linux_error(smb_buffer_response); now done in SendReceive */
2376 } else if ((smb_buffer_response->WordCount == 3)
2377 || (smb_buffer_response->WordCount == 4)) {
2378 __u16 action = le16_to_cpu(pSMBr->resp.Action);
2379 __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2380 if (action & GUEST_LOGIN)
50c2f753
SF
2381 cFYI(1, (" Guest login")); /* BB mark SesInfo struct? */
2382 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format
2383 (little endian) */
1da177e4 2384 cFYI(1, ("UID = %d ", ses->Suid));
50c2f753
SF
2385 /* response can have either 3 or 4 word count - Samba sends 3 */
2386 bcc_ptr = pByteArea(smb_buffer_response);
1da177e4
LT
2387 if ((pSMBr->resp.hdr.WordCount == 3)
2388 || ((pSMBr->resp.hdr.WordCount == 4)
2389 && (blob_len < pSMBr->resp.ByteCount))) {
2390 if (pSMBr->resp.hdr.WordCount == 4)
2391 bcc_ptr += blob_len;
2392
2393 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2394 if ((long) (bcc_ptr) % 2) {
2395 remaining_words =
50c2f753
SF
2396 (BCC(smb_buffer_response) - 1) / 2;
2397 /* Unicode strings must be word
2398 aligned */
2399 bcc_ptr++;
1da177e4
LT
2400 } else {
2401 remaining_words =
2402 BCC(smb_buffer_response) / 2;
2403 }
2404 len =
2405 UniStrnlen((wchar_t *) bcc_ptr,
2406 remaining_words - 1);
2407/* We look for obvious messed up bcc or strings in response so we do not go off
2408 the end since (at least) WIN2K and Windows XP have a major bug in not null
2409 terminating last Unicode string in response */
fb8c4b14 2410 if (ses->serverOS)
a424f8bf 2411 kfree(ses->serverOS);
50c2f753
SF
2412 ses->serverOS = kzalloc(2 * (len + 1),
2413 GFP_KERNEL);
fb8c4b14 2414 if (ses->serverOS == NULL)
433dc24f 2415 goto sesssetup_nomem;
1da177e4 2416 cifs_strfromUCS_le(ses->serverOS,
50c2f753
SF
2417 (__le16 *)bcc_ptr,
2418 len, nls_codepage);
1da177e4
LT
2419 bcc_ptr += 2 * (len + 1);
2420 remaining_words -= len + 1;
2421 ses->serverOS[2 * len] = 0;
2422 ses->serverOS[1 + (2 * len)] = 0;
2423 if (remaining_words > 0) {
2424 len = UniStrnlen((wchar_t *)bcc_ptr,
2425 remaining_words-1);
cd49b492 2426 kfree(ses->serverNOS);
50c2f753
SF
2427 ses->serverNOS = kzalloc(2 * (len + 1),
2428 GFP_KERNEL);
fb8c4b14 2429 if (ses->serverNOS == NULL)
433dc24f 2430 goto sesssetup_nomem;
1da177e4 2431 cifs_strfromUCS_le(ses->serverNOS,
50c2f753
SF
2432 (__le16 *)bcc_ptr,
2433 len, nls_codepage);
1da177e4
LT
2434 bcc_ptr += 2 * (len + 1);
2435 ses->serverNOS[2 * len] = 0;
2436 ses->serverNOS[1 + (2 * len)] = 0;
fb8c4b14 2437 if (strncmp(ses->serverNOS,
50c2f753 2438 "NT LAN Manager 4", 16) == 0) {
467a8f8d 2439 cFYI(1, ("NT4 server"));
1da177e4
LT
2440 ses->flags |= CIFS_SES_NT4;
2441 }
2442 remaining_words -= len + 1;
2443 if (remaining_words > 0) {
433dc24f 2444 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
50c2f753
SF
2445 /* last string is not always null terminated
2446 (for e.g. for Windows XP & 2000) */
fb8c4b14 2447 if (ses->serverDomain)
a424f8bf 2448 kfree(ses->serverDomain);
1da177e4 2449 ses->serverDomain =
50c2f753
SF
2450 kzalloc(2*(len+1),
2451 GFP_KERNEL);
fb8c4b14 2452 if (ses->serverDomain == NULL)
433dc24f 2453 goto sesssetup_nomem;
1da177e4 2454 cifs_strfromUCS_le(ses->serverDomain,
50c2f753
SF
2455 (__le16 *)bcc_ptr,
2456 len, nls_codepage);
1da177e4
LT
2457 bcc_ptr += 2 * (len + 1);
2458 ses->serverDomain[2*len] = 0;
2459 ses->serverDomain[1+(2*len)] = 0;
50c2f753
SF
2460 } else { /* else no more room so create
2461 dummy domain string */
fb8c4b14 2462 if (ses->serverDomain)
a424f8bf 2463 kfree(ses->serverDomain);
50c2f753 2464 ses->serverDomain =
e915fc49 2465 kzalloc(2, GFP_KERNEL);
a424f8bf 2466 }
50c2f753
SF
2467 } else { /* no room so create dummy domain
2468 and NOS string */
2469
433dc24f
SF
2470 /* if these kcallocs fail not much we
2471 can do, but better to not fail the
2472 sesssetup itself */
cd49b492 2473 kfree(ses->serverDomain);
1da177e4 2474 ses->serverDomain =
e915fc49 2475 kzalloc(2, GFP_KERNEL);
cd49b492 2476 kfree(ses->serverNOS);
1da177e4 2477 ses->serverNOS =
e915fc49 2478 kzalloc(2, GFP_KERNEL);
1da177e4
LT
2479 }
2480 } else { /* ASCII */
2481 len = strnlen(bcc_ptr, 1024);
2482 if (((long) bcc_ptr + len) - (long)
2483 pByteArea(smb_buffer_response)
2484 <= BCC(smb_buffer_response)) {
cd49b492 2485 kfree(ses->serverOS);
50c2f753
SF
2486 ses->serverOS = kzalloc(len + 1,
2487 GFP_KERNEL);
fb8c4b14 2488 if (ses->serverOS == NULL)
433dc24f 2489 goto sesssetup_nomem;
50c2f753 2490 strncpy(ses->serverOS, bcc_ptr, len);
1da177e4
LT
2491
2492 bcc_ptr += len;
50c2f753
SF
2493 /* null terminate the string */
2494 bcc_ptr[0] = 0;
1da177e4
LT
2495 bcc_ptr++;
2496
2497 len = strnlen(bcc_ptr, 1024);
cd49b492 2498 kfree(ses->serverNOS);
50c2f753
SF
2499 ses->serverNOS = kzalloc(len + 1,
2500 GFP_KERNEL);
fb8c4b14 2501 if (ses->serverNOS == NULL)
433dc24f 2502 goto sesssetup_nomem;
1da177e4
LT
2503 strncpy(ses->serverNOS, bcc_ptr, len);
2504 bcc_ptr += len;
2505 bcc_ptr[0] = 0;
2506 bcc_ptr++;
2507
2508 len = strnlen(bcc_ptr, 1024);
fb8c4b14 2509 if (ses->serverDomain)
a424f8bf 2510 kfree(ses->serverDomain);
50c2f753
SF
2511 ses->serverDomain = kzalloc(len + 1,
2512 GFP_KERNEL);
fb8c4b14 2513 if (ses->serverDomain == NULL)
433dc24f 2514 goto sesssetup_nomem;
50c2f753
SF
2515 strncpy(ses->serverDomain, bcc_ptr,
2516 len);
1da177e4
LT
2517 bcc_ptr += len;
2518 bcc_ptr[0] = 0;
2519 bcc_ptr++;
2520 } else
2521 cFYI(1,
50c2f753
SF
2522 ("Variable field of length %d "
2523 "extends beyond end of smb ",
1da177e4
LT
2524 len));
2525 }
2526 } else {
2527 cERROR(1,
50c2f753
SF
2528 (" Security Blob Length extends beyond "
2529 "end of SMB"));
1da177e4
LT
2530 }
2531 } else {
2532 cERROR(1,
2533 (" Invalid Word count %d: ",
2534 smb_buffer_response->WordCount));
2535 rc = -EIO;
2536 }
433dc24f
SF
2537sesssetup_nomem: /* do not return an error on nomem for the info strings,
2538 since that could make reconnection harder, and
2539 reconnection might be needed to free memory */
a8a11d39 2540 cifs_buf_release(smb_buffer);
1da177e4
LT
2541
2542 return rc;
2543}
2544
1da177e4
LT
2545static int
2546CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
50c2f753 2547 struct cifsSesInfo *ses, int *pNTLMv2_flag,
1da177e4
LT
2548 const struct nls_table *nls_codepage)
2549{
2550 struct smb_hdr *smb_buffer;
2551 struct smb_hdr *smb_buffer_response;
2552 SESSION_SETUP_ANDX *pSMB;
2553 SESSION_SETUP_ANDX *pSMBr;
2554 char *bcc_ptr;
2555 char *domain;
2556 int rc = 0;
2557 int remaining_words = 0;
2558 int bytes_returned = 0;
2559 int len;
6345a3a8 2560 int SecurityBlobLength = sizeof(NEGOTIATE_MESSAGE);
1da177e4
LT
2561 PNEGOTIATE_MESSAGE SecurityBlob;
2562 PCHALLENGE_MESSAGE SecurityBlob2;
2563 __u32 negotiate_flags, capabilities;
2564 __u16 count;
2565
12b3b8ff 2566 cFYI(1, ("In NTLMSSP sesssetup (negotiate)"));
fb8c4b14 2567 if (ses == NULL)
1da177e4
LT
2568 return -EINVAL;
2569 domain = ses->domainName;
2570 *pNTLMv2_flag = FALSE;
2571 smb_buffer = cifs_buf_get();
2572 if (smb_buffer == NULL) {
2573 return -ENOMEM;
2574 }
2575 smb_buffer_response = smb_buffer;
2576 pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2577 pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response;
2578
2579 /* send SMBsessionSetup here */
2580 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2581 NULL /* no tCon exists yet */ , 12 /* wct */ );
1982c344
SF
2582
2583 smb_buffer->Mid = GetNextMid(ses->server);
1da177e4
LT
2584 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2585 pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
2586
2587 pSMB->req.AndXCommand = 0xFF;
2588 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2589 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2590
fb8c4b14 2591 if (ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
1da177e4
LT
2592 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2593
2594 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2595 CAP_EXTENDED_SECURITY;
2596 if (ses->capabilities & CAP_UNICODE) {
2597 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2598 capabilities |= CAP_UNICODE;
2599 }
2600 if (ses->capabilities & CAP_STATUS32) {
2601 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2602 capabilities |= CAP_STATUS32;
2603 }
2604 if (ses->capabilities & CAP_DFS) {
2605 smb_buffer->Flags2 |= SMBFLG2_DFS;
2606 capabilities |= CAP_DFS;
2607 }
2608 pSMB->req.Capabilities = cpu_to_le32(capabilities);
2609
2610 bcc_ptr = (char *) &pSMB->req.SecurityBlob;
2611 SecurityBlob = (PNEGOTIATE_MESSAGE) bcc_ptr;
2612 strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
2613 SecurityBlob->MessageType = NtLmNegotiate;
2614 negotiate_flags =
2615 NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_NEGOTIATE_OEM |
12b3b8ff
SF
2616 NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_NTLM |
2617 NTLMSSP_NEGOTIATE_56 |
1da177e4 2618 /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN | */ NTLMSSP_NEGOTIATE_128;
fb8c4b14 2619 if (sign_CIFS_PDUs)
1da177e4 2620 negotiate_flags |= NTLMSSP_NEGOTIATE_SIGN;
fb8c4b14 2621/* if (ntlmv2_support)
3979877e 2622 negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;*/
1da177e4
LT
2623 /* setup pointers to domain name and workstation name */
2624 bcc_ptr += SecurityBlobLength;
2625
2626 SecurityBlob->WorkstationName.Buffer = 0;
2627 SecurityBlob->WorkstationName.Length = 0;
2628 SecurityBlob->WorkstationName.MaximumLength = 0;
2629
12b3b8ff
SF
2630 /* Domain not sent on first Sesssetup in NTLMSSP, instead it is sent
2631 along with username on auth request (ie the response to challenge) */
2632 SecurityBlob->DomainName.Buffer = 0;
2633 SecurityBlob->DomainName.Length = 0;
2634 SecurityBlob->DomainName.MaximumLength = 0;
1da177e4
LT
2635 if (ses->capabilities & CAP_UNICODE) {
2636 if ((long) bcc_ptr % 2) {
2637 *bcc_ptr = 0;
2638 bcc_ptr++;
2639 }
2640
2641 bytes_returned =
e89dc920 2642 cifs_strtoUCS((__le16 *) bcc_ptr, "Linux version ",
1da177e4
LT
2643 32, nls_codepage);
2644 bcc_ptr += 2 * bytes_returned;
2645 bytes_returned =
e9ff3990 2646 cifs_strtoUCS((__le16 *) bcc_ptr, utsname()->release, 32,
1da177e4
LT
2647 nls_codepage);
2648 bcc_ptr += 2 * bytes_returned;
2649 bcc_ptr += 2; /* null terminate Linux version */
2650 bytes_returned =
e89dc920 2651 cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
1da177e4
LT
2652 64, nls_codepage);
2653 bcc_ptr += 2 * bytes_returned;
2654 *(bcc_ptr + 1) = 0;
2655 *(bcc_ptr + 2) = 0;
2656 bcc_ptr += 2; /* null terminate network opsys string */
2657 *(bcc_ptr + 1) = 0;
2658 *(bcc_ptr + 2) = 0;
2659 bcc_ptr += 2; /* null domain */
2660 } else { /* ASCII */
2661 strcpy(bcc_ptr, "Linux version ");
2662 bcc_ptr += strlen("Linux version ");
e9ff3990
SH
2663 strcpy(bcc_ptr, utsname()->release);
2664 bcc_ptr += strlen(utsname()->release) + 1;
1da177e4
LT
2665 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2666 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2667 bcc_ptr++; /* empty domain field */
2668 *bcc_ptr = 0;
2669 }
2670 SecurityBlob->NegotiateFlags = cpu_to_le32(negotiate_flags);
2671 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
2672 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2673 smb_buffer->smb_buf_length += count;
2674 pSMB->req.ByteCount = cpu_to_le16(count);
2675
2676 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2677 &bytes_returned, 1);
2678
2679 if (smb_buffer_response->Status.CifsError ==
2680 cpu_to_le32(NT_STATUS_MORE_PROCESSING_REQUIRED))
2681 rc = 0;
2682
2683 if (rc) {
2684/* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
2685 } else if ((smb_buffer_response->WordCount == 3)
2686 || (smb_buffer_response->WordCount == 4)) {
2687 __u16 action = le16_to_cpu(pSMBr->resp.Action);
2688 __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2689
2690 if (action & GUEST_LOGIN)
50c2f753
SF
2691 cFYI(1, (" Guest login"));
2692 /* Do we want to set anything in SesInfo struct when guest login? */
1da177e4 2693
50c2f753
SF
2694 bcc_ptr = pByteArea(smb_buffer_response);
2695 /* response can have either 3 or 4 word count - Samba sends 3 */
1da177e4
LT
2696
2697 SecurityBlob2 = (PCHALLENGE_MESSAGE) bcc_ptr;
2698 if (SecurityBlob2->MessageType != NtLmChallenge) {
2699 cFYI(1,
2700 ("Unexpected NTLMSSP message type received %d",
2701 SecurityBlob2->MessageType));
2702 } else if (ses) {
50c2f753 2703 ses->Suid = smb_buffer_response->Uid; /* UID left in le format */
12b3b8ff 2704 cFYI(1, ("UID = %d", ses->Suid));
1da177e4
LT
2705 if ((pSMBr->resp.hdr.WordCount == 3)
2706 || ((pSMBr->resp.hdr.WordCount == 4)
2707 && (blob_len <
2708 pSMBr->resp.ByteCount))) {
2709
2710 if (pSMBr->resp.hdr.WordCount == 4) {
2711 bcc_ptr += blob_len;
12b3b8ff 2712 cFYI(1, ("Security Blob Length %d",
1da177e4
LT
2713 blob_len));
2714 }
2715
12b3b8ff 2716 cFYI(1, ("NTLMSSP Challenge rcvd"));
1da177e4
LT
2717
2718 memcpy(ses->server->cryptKey,
2719 SecurityBlob2->Challenge,
2720 CIFS_CRYPTO_KEY_SIZE);
50c2f753 2721 if (SecurityBlob2->NegotiateFlags &
12b3b8ff 2722 cpu_to_le32(NTLMSSP_NEGOTIATE_NTLMV2))
1da177e4
LT
2723 *pNTLMv2_flag = TRUE;
2724
50c2f753
SF
2725 if ((SecurityBlob2->NegotiateFlags &
2726 cpu_to_le32(NTLMSSP_NEGOTIATE_ALWAYS_SIGN))
1da177e4 2727 || (sign_CIFS_PDUs > 1))
50c2f753
SF
2728 ses->server->secMode |=
2729 SECMODE_SIGN_REQUIRED;
2730 if ((SecurityBlob2->NegotiateFlags &
1da177e4 2731 cpu_to_le32(NTLMSSP_NEGOTIATE_SIGN)) && (sign_CIFS_PDUs))
50c2f753 2732 ses->server->secMode |=
1da177e4
LT
2733 SECMODE_SIGN_ENABLED;
2734
2735 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2736 if ((long) (bcc_ptr) % 2) {
2737 remaining_words =
2738 (BCC(smb_buffer_response)
2739 - 1) / 2;
50c2f753
SF
2740 /* Must word align unicode strings */
2741 bcc_ptr++;
1da177e4
LT
2742 } else {
2743 remaining_words =
2744 BCC
2745 (smb_buffer_response) / 2;
2746 }
2747 len =
2748 UniStrnlen((wchar_t *) bcc_ptr,
2749 remaining_words - 1);
2750/* We look for obvious messed up bcc or strings in response so we do not go off
2751 the end since (at least) WIN2K and Windows XP have a major bug in not null
2752 terminating last Unicode string in response */
fb8c4b14 2753 if (ses->serverOS)
a424f8bf 2754 kfree(ses->serverOS);
1da177e4 2755 ses->serverOS =
e915fc49 2756 kzalloc(2 * (len + 1), GFP_KERNEL);
1da177e4 2757 cifs_strfromUCS_le(ses->serverOS,
e89dc920 2758 (__le16 *)
1da177e4
LT
2759 bcc_ptr, len,
2760 nls_codepage);
2761 bcc_ptr += 2 * (len + 1);
2762 remaining_words -= len + 1;
2763 ses->serverOS[2 * len] = 0;
2764 ses->serverOS[1 + (2 * len)] = 0;
2765 if (remaining_words > 0) {
2766 len = UniStrnlen((wchar_t *)
2767 bcc_ptr,
2768 remaining_words
2769 - 1);
cd49b492 2770 kfree(ses->serverNOS);
1da177e4 2771 ses->serverNOS =
e915fc49 2772 kzalloc(2 * (len + 1),
1da177e4
LT
2773 GFP_KERNEL);
2774 cifs_strfromUCS_le(ses->
2775 serverNOS,
e89dc920 2776 (__le16 *)
1da177e4
LT
2777 bcc_ptr,
2778 len,
2779 nls_codepage);
2780 bcc_ptr += 2 * (len + 1);
2781 ses->serverNOS[2 * len] = 0;
2782 ses->serverNOS[1 +
2783 (2 * len)] = 0;
2784 remaining_words -= len + 1;
2785 if (remaining_words > 0) {
50c2f753
SF
2786 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2787 /* last string not always null terminated
2788 (for e.g. for Windows XP & 2000) */
cd49b492 2789 kfree(ses->serverDomain);
1da177e4 2790 ses->serverDomain =
e915fc49 2791 kzalloc(2 *
1da177e4
LT
2792 (len +
2793 1),
2794 GFP_KERNEL);
2795 cifs_strfromUCS_le
e89dc920
SF
2796 (ses->serverDomain,
2797 (__le16 *)bcc_ptr,
2798 len, nls_codepage);
1da177e4
LT
2799 bcc_ptr +=
2800 2 * (len + 1);
e89dc920 2801 ses->serverDomain[2*len]
1da177e4 2802 = 0;
e89dc920
SF
2803 ses->serverDomain
2804 [1 + (2 * len)]
1da177e4
LT
2805 = 0;
2806 } /* else no more room so create dummy domain string */
a424f8bf 2807 else {
cd49b492 2808 kfree(ses->serverDomain);
1da177e4 2809 ses->serverDomain =
e915fc49 2810 kzalloc(2,
1da177e4 2811 GFP_KERNEL);
a424f8bf 2812 }
1da177e4 2813 } else { /* no room so create dummy domain and NOS string */
cd49b492 2814 kfree(ses->serverDomain);
1da177e4 2815 ses->serverDomain =
e915fc49 2816 kzalloc(2, GFP_KERNEL);
cd49b492 2817 kfree(ses->serverNOS);
1da177e4 2818 ses->serverNOS =
e915fc49 2819 kzalloc(2, GFP_KERNEL);
1da177e4
LT
2820 }
2821 } else { /* ASCII */
2822 len = strnlen(bcc_ptr, 1024);
2823 if (((long) bcc_ptr + len) - (long)
2824 pByteArea(smb_buffer_response)
2825 <= BCC(smb_buffer_response)) {
fb8c4b14 2826 if (ses->serverOS)
a424f8bf 2827 kfree(ses->serverOS);
1da177e4 2828 ses->serverOS =
e915fc49 2829 kzalloc(len + 1,
1da177e4
LT
2830 GFP_KERNEL);
2831 strncpy(ses->serverOS,
2832 bcc_ptr, len);
2833
2834 bcc_ptr += len;
2835 bcc_ptr[0] = 0; /* null terminate string */
2836 bcc_ptr++;
2837
2838 len = strnlen(bcc_ptr, 1024);
cd49b492 2839 kfree(ses->serverNOS);
1da177e4 2840 ses->serverNOS =
e915fc49 2841 kzalloc(len + 1,
1da177e4
LT
2842 GFP_KERNEL);
2843 strncpy(ses->serverNOS, bcc_ptr, len);
2844 bcc_ptr += len;
2845 bcc_ptr[0] = 0;
2846 bcc_ptr++;
2847
2848 len = strnlen(bcc_ptr, 1024);
cd49b492 2849 kfree(ses->serverDomain);
1da177e4 2850 ses->serverDomain =
e915fc49 2851 kzalloc(len + 1,
1da177e4 2852 GFP_KERNEL);
50c2f753
SF
2853 strncpy(ses->serverDomain,
2854 bcc_ptr, len);
1da177e4
LT
2855 bcc_ptr += len;
2856 bcc_ptr[0] = 0;
2857 bcc_ptr++;
2858 } else
2859 cFYI(1,
63135e08
SF
2860 ("field of length %d "
2861 "extends beyond end of smb",
1da177e4
LT
2862 len));
2863 }
2864 } else {
50c2f753
SF
2865 cERROR(1, ("Security Blob Length extends beyond"
2866 " end of SMB"));
1da177e4
LT
2867 }
2868 } else {
2869 cERROR(1, ("No session structure passed in."));
2870 }
2871 } else {
2872 cERROR(1,
5815449d 2873 (" Invalid Word count %d:",
1da177e4
LT
2874 smb_buffer_response->WordCount));
2875 rc = -EIO;
2876 }
2877
a8a11d39 2878 cifs_buf_release(smb_buffer);
1da177e4
LT
2879
2880 return rc;
2881}
2882static int
2883CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
6345a3a8
CG
2884 char *ntlm_session_key, int ntlmv2_flag,
2885 const struct nls_table *nls_codepage)
1da177e4
LT
2886{
2887 struct smb_hdr *smb_buffer;
2888 struct smb_hdr *smb_buffer_response;
2889 SESSION_SETUP_ANDX *pSMB;
2890 SESSION_SETUP_ANDX *pSMBr;
2891 char *bcc_ptr;
2892 char *user;
2893 char *domain;
2894 int rc = 0;
2895 int remaining_words = 0;
2896 int bytes_returned = 0;
2897 int len;
6345a3a8 2898 int SecurityBlobLength = sizeof(AUTHENTICATE_MESSAGE);
1da177e4
LT
2899 PAUTHENTICATE_MESSAGE SecurityBlob;
2900 __u32 negotiate_flags, capabilities;
2901 __u16 count;
2902
2903 cFYI(1, ("In NTLMSSPSessSetup (Authenticate)"));
fb8c4b14 2904 if (ses == NULL)
1da177e4
LT
2905 return -EINVAL;
2906 user = ses->userName;
2907 domain = ses->domainName;
2908 smb_buffer = cifs_buf_get();
2909 if (smb_buffer == NULL) {
2910 return -ENOMEM;
2911 }
2912 smb_buffer_response = smb_buffer;
6345a3a8
CG
2913 pSMB = (SESSION_SETUP_ANDX *)smb_buffer;
2914 pSMBr = (SESSION_SETUP_ANDX *)smb_buffer_response;
1da177e4
LT
2915
2916 /* send SMBsessionSetup here */
2917 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2918 NULL /* no tCon exists yet */ , 12 /* wct */ );
1982c344
SF
2919
2920 smb_buffer->Mid = GetNextMid(ses->server);
1da177e4
LT
2921 pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
2922 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2923 pSMB->req.AndXCommand = 0xFF;
2924 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2925 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2926
2927 pSMB->req.hdr.Uid = ses->Suid;
2928
fb8c4b14 2929 if (ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
1da177e4
LT
2930 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2931
2932 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
6345a3a8 2933 CAP_EXTENDED_SECURITY;
1da177e4
LT
2934 if (ses->capabilities & CAP_UNICODE) {
2935 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2936 capabilities |= CAP_UNICODE;
2937 }
2938 if (ses->capabilities & CAP_STATUS32) {
2939 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2940 capabilities |= CAP_STATUS32;
2941 }
2942 if (ses->capabilities & CAP_DFS) {
2943 smb_buffer->Flags2 |= SMBFLG2_DFS;
2944 capabilities |= CAP_DFS;
2945 }
2946 pSMB->req.Capabilities = cpu_to_le32(capabilities);
2947
6345a3a8
CG
2948 bcc_ptr = (char *)&pSMB->req.SecurityBlob;
2949 SecurityBlob = (PAUTHENTICATE_MESSAGE)bcc_ptr;
1da177e4
LT
2950 strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
2951 SecurityBlob->MessageType = NtLmAuthenticate;
2952 bcc_ptr += SecurityBlobLength;
6345a3a8
CG
2953 negotiate_flags = NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_REQUEST_TARGET |
2954 NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_TARGET_INFO |
2955 0x80000000 | NTLMSSP_NEGOTIATE_128;
fb8c4b14 2956 if (sign_CIFS_PDUs)
1da177e4 2957 negotiate_flags |= /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN |*/ NTLMSSP_NEGOTIATE_SIGN;
fb8c4b14 2958 if (ntlmv2_flag)
1da177e4
LT
2959 negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;
2960
2961/* setup pointers to domain name and workstation name */
2962
2963 SecurityBlob->WorkstationName.Buffer = 0;
2964 SecurityBlob->WorkstationName.Length = 0;
2965 SecurityBlob->WorkstationName.MaximumLength = 0;
2966 SecurityBlob->SessionKey.Length = 0;
2967 SecurityBlob->SessionKey.MaximumLength = 0;
2968 SecurityBlob->SessionKey.Buffer = 0;
2969
2970 SecurityBlob->LmChallengeResponse.Length = 0;
2971 SecurityBlob->LmChallengeResponse.MaximumLength = 0;
2972 SecurityBlob->LmChallengeResponse.Buffer = 0;
2973
2974 SecurityBlob->NtChallengeResponse.Length =
7c7b25bc 2975 cpu_to_le16(CIFS_SESS_KEY_SIZE);
1da177e4 2976 SecurityBlob->NtChallengeResponse.MaximumLength =
7c7b25bc
SF
2977 cpu_to_le16(CIFS_SESS_KEY_SIZE);
2978 memcpy(bcc_ptr, ntlm_session_key, CIFS_SESS_KEY_SIZE);
1da177e4
LT
2979 SecurityBlob->NtChallengeResponse.Buffer =
2980 cpu_to_le32(SecurityBlobLength);
7c7b25bc
SF
2981 SecurityBlobLength += CIFS_SESS_KEY_SIZE;
2982 bcc_ptr += CIFS_SESS_KEY_SIZE;
1da177e4
LT
2983
2984 if (ses->capabilities & CAP_UNICODE) {
2985 if (domain == NULL) {
2986 SecurityBlob->DomainName.Buffer = 0;
2987 SecurityBlob->DomainName.Length = 0;
2988 SecurityBlob->DomainName.MaximumLength = 0;
2989 } else {
77159b4d 2990 __u16 ln = cifs_strtoUCS((__le16 *) bcc_ptr, domain, 64,
1da177e4 2991 nls_codepage);
77159b4d 2992 ln *= 2;
1da177e4 2993 SecurityBlob->DomainName.MaximumLength =
77159b4d 2994 cpu_to_le16(ln);
1da177e4
LT
2995 SecurityBlob->DomainName.Buffer =
2996 cpu_to_le32(SecurityBlobLength);
77159b4d
SF
2997 bcc_ptr += ln;
2998 SecurityBlobLength += ln;
2999 SecurityBlob->DomainName.Length = cpu_to_le16(ln);
1da177e4
LT
3000 }
3001 if (user == NULL) {
3002 SecurityBlob->UserName.Buffer = 0;
3003 SecurityBlob->UserName.Length = 0;
3004 SecurityBlob->UserName.MaximumLength = 0;
3005 } else {
77159b4d 3006 __u16 ln = cifs_strtoUCS((__le16 *) bcc_ptr, user, 64,
1da177e4 3007 nls_codepage);
77159b4d 3008 ln *= 2;
1da177e4 3009 SecurityBlob->UserName.MaximumLength =
77159b4d 3010 cpu_to_le16(ln);
1da177e4
LT
3011 SecurityBlob->UserName.Buffer =
3012 cpu_to_le32(SecurityBlobLength);
77159b4d
SF
3013 bcc_ptr += ln;
3014 SecurityBlobLength += ln;
3015 SecurityBlob->UserName.Length = cpu_to_le16(ln);
1da177e4
LT
3016 }
3017
63135e08
SF
3018 /* SecurityBlob->WorkstationName.Length =
3019 cifs_strtoUCS((__le16 *) bcc_ptr, "AMACHINE",64, nls_codepage);
1da177e4 3020 SecurityBlob->WorkstationName.Length *= 2;
63135e08
SF
3021 SecurityBlob->WorkstationName.MaximumLength =
3022 cpu_to_le16(SecurityBlob->WorkstationName.Length);
3023 SecurityBlob->WorkstationName.Buffer =
3024 cpu_to_le32(SecurityBlobLength);
1da177e4
LT
3025 bcc_ptr += SecurityBlob->WorkstationName.Length;
3026 SecurityBlobLength += SecurityBlob->WorkstationName.Length;
63135e08
SF
3027 SecurityBlob->WorkstationName.Length =
3028 cpu_to_le16(SecurityBlob->WorkstationName.Length); */
1da177e4
LT
3029
3030 if ((long) bcc_ptr % 2) {
3031 *bcc_ptr = 0;
3032 bcc_ptr++;
3033 }
3034 bytes_returned =
e89dc920 3035 cifs_strtoUCS((__le16 *) bcc_ptr, "Linux version ",
1da177e4
LT
3036 32, nls_codepage);
3037 bcc_ptr += 2 * bytes_returned;
3038 bytes_returned =
e9ff3990 3039 cifs_strtoUCS((__le16 *) bcc_ptr, utsname()->release, 32,
1da177e4
LT
3040 nls_codepage);
3041 bcc_ptr += 2 * bytes_returned;
3042 bcc_ptr += 2; /* null term version string */
3043 bytes_returned =
e89dc920 3044 cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
1da177e4
LT
3045 64, nls_codepage);
3046 bcc_ptr += 2 * bytes_returned;
3047 *(bcc_ptr + 1) = 0;
3048 *(bcc_ptr + 2) = 0;
3049 bcc_ptr += 2; /* null terminate network opsys string */
3050 *(bcc_ptr + 1) = 0;
3051 *(bcc_ptr + 2) = 0;
3052 bcc_ptr += 2; /* null domain */
3053 } else { /* ASCII */
3054 if (domain == NULL) {
3055 SecurityBlob->DomainName.Buffer = 0;
3056 SecurityBlob->DomainName.Length = 0;
3057 SecurityBlob->DomainName.MaximumLength = 0;
3058 } else {
77159b4d 3059 __u16 ln;
1da177e4
LT
3060 negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
3061 strncpy(bcc_ptr, domain, 63);
77159b4d 3062 ln = strnlen(domain, 64);
1da177e4 3063 SecurityBlob->DomainName.MaximumLength =
77159b4d 3064 cpu_to_le16(ln);
1da177e4
LT
3065 SecurityBlob->DomainName.Buffer =
3066 cpu_to_le32(SecurityBlobLength);
77159b4d
SF
3067 bcc_ptr += ln;
3068 SecurityBlobLength += ln;
3069 SecurityBlob->DomainName.Length = cpu_to_le16(ln);
1da177e4
LT
3070 }
3071 if (user == NULL) {
3072 SecurityBlob->UserName.Buffer = 0;
3073 SecurityBlob->UserName.Length = 0;
3074 SecurityBlob->UserName.MaximumLength = 0;
3075 } else {
77159b4d 3076 __u16 ln;
1da177e4 3077 strncpy(bcc_ptr, user, 63);
77159b4d
SF
3078 ln = strnlen(user, 64);
3079 SecurityBlob->UserName.MaximumLength = cpu_to_le16(ln);
1da177e4 3080 SecurityBlob->UserName.Buffer =
77159b4d
SF
3081 cpu_to_le32(SecurityBlobLength);
3082 bcc_ptr += ln;
3083 SecurityBlobLength += ln;
3084 SecurityBlob->UserName.Length = cpu_to_le16(ln);
1da177e4
LT
3085 }
3086 /* BB fill in our workstation name if known BB */
3087
3088 strcpy(bcc_ptr, "Linux version ");
3089 bcc_ptr += strlen("Linux version ");
e9ff3990
SH
3090 strcpy(bcc_ptr, utsname()->release);
3091 bcc_ptr += strlen(utsname()->release) + 1;
1da177e4
LT
3092 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
3093 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
3094 bcc_ptr++; /* null domain */
3095 *bcc_ptr = 0;
3096 }
3097 SecurityBlob->NegotiateFlags = cpu_to_le32(negotiate_flags);
3098 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
3099 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
3100 smb_buffer->smb_buf_length += count;
3101 pSMB->req.ByteCount = cpu_to_le16(count);
3102
3103 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
3104 &bytes_returned, 1);
3105 if (rc) {
6345a3a8
CG
3106/* rc = map_smb_to_linux_error(smb_buffer_response) done in SendReceive now */
3107 } else if ((smb_buffer_response->WordCount == 3) ||
3108 (smb_buffer_response->WordCount == 4)) {
1da177e4 3109 __u16 action = le16_to_cpu(pSMBr->resp.Action);
6345a3a8 3110 __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
1da177e4 3111 if (action & GUEST_LOGIN)
50c2f753
SF
3112 cFYI(1, (" Guest login")); /* BB Should we set anything
3113 in SesInfo struct ? */
3114/* if (SecurityBlob2->MessageType != NtLm??) {
3115 cFYI("Unexpected message type on auth response is %d"));
3116 } */
3117
1da177e4
LT
3118 if (ses) {
3119 cFYI(1,
50c2f753 3120 ("Check challenge UID %d vs auth response UID %d",
1da177e4 3121 ses->Suid, smb_buffer_response->Uid));
50c2f753
SF
3122 /* UID left in wire format */
3123 ses->Suid = smb_buffer_response->Uid;
3124 bcc_ptr = pByteArea(smb_buffer_response);
3125 /* response can have either 3 or 4 word count - Samba sends 3 */
1da177e4
LT
3126 if ((pSMBr->resp.hdr.WordCount == 3)
3127 || ((pSMBr->resp.hdr.WordCount == 4)
3128 && (blob_len <
3129 pSMBr->resp.ByteCount))) {
3130 if (pSMBr->resp.hdr.WordCount == 4) {
3131 bcc_ptr +=
3132 blob_len;
3133 cFYI(1,
3134 ("Security Blob Length %d ",
3135 blob_len));
3136 }
3137
3138 cFYI(1,
3139 ("NTLMSSP response to Authenticate "));
3140
3141 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
3142 if ((long) (bcc_ptr) % 2) {
3143 remaining_words =
3144 (BCC(smb_buffer_response)
3145 - 1) / 2;
3146 bcc_ptr++; /* Unicode strings must be word aligned */
3147 } else {
3148 remaining_words = BCC(smb_buffer_response) / 2;
3149 }
77159b4d
SF
3150 len = UniStrnlen((wchar_t *) bcc_ptr,
3151 remaining_words - 1);
1da177e4
LT
3152/* We look for obvious messed up bcc or strings in response so we do not go off
3153 the end since (at least) WIN2K and Windows XP have a major bug in not null
3154 terminating last Unicode string in response */
fb8c4b14 3155 if (ses->serverOS)
08775834 3156 kfree(ses->serverOS);
1da177e4 3157 ses->serverOS =
e915fc49 3158 kzalloc(2 * (len + 1), GFP_KERNEL);
1da177e4 3159 cifs_strfromUCS_le(ses->serverOS,
e89dc920 3160 (__le16 *)
1da177e4
LT
3161 bcc_ptr, len,
3162 nls_codepage);
3163 bcc_ptr += 2 * (len + 1);
3164 remaining_words -= len + 1;
3165 ses->serverOS[2 * len] = 0;
3166 ses->serverOS[1 + (2 * len)] = 0;
3167 if (remaining_words > 0) {
3168 len = UniStrnlen((wchar_t *)
3169 bcc_ptr,
3170 remaining_words
3171 - 1);
cd49b492 3172 kfree(ses->serverNOS);
1da177e4 3173 ses->serverNOS =
e915fc49 3174 kzalloc(2 * (len + 1),
1da177e4
LT
3175 GFP_KERNEL);
3176 cifs_strfromUCS_le(ses->
3177 serverNOS,
e89dc920 3178 (__le16 *)
1da177e4
LT
3179 bcc_ptr,
3180 len,
3181 nls_codepage);
3182 bcc_ptr += 2 * (len + 1);
3183 ses->serverNOS[2 * len] = 0;
3184 ses->serverNOS[1+(2*len)] = 0;
3185 remaining_words -= len + 1;
3186 if (remaining_words > 0) {
50c2f753 3187 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
1da177e4 3188 /* last string not always null terminated (e.g. for Windows XP & 2000) */
fb8c4b14 3189 if (ses->serverDomain)
a424f8bf 3190 kfree(ses->serverDomain);
1da177e4 3191 ses->serverDomain =
e915fc49 3192 kzalloc(2 *
1da177e4
LT
3193 (len +
3194 1),
3195 GFP_KERNEL);
3196 cifs_strfromUCS_le
3197 (ses->
3198 serverDomain,
e89dc920 3199 (__le16 *)
1da177e4
LT
3200 bcc_ptr, len,
3201 nls_codepage);
3202 bcc_ptr +=
3203 2 * (len + 1);
3204 ses->
3205 serverDomain[2
3206 * len]
3207 = 0;
3208 ses->
3209 serverDomain[1
3210 +
3211 (2
3212 *
3213 len)]
3214 = 0;
3215 } /* else no more room so create dummy domain string */
a424f8bf 3216 else {
fb8c4b14 3217 if (ses->serverDomain)
a424f8bf 3218 kfree(ses->serverDomain);
e915fc49 3219 ses->serverDomain = kzalloc(2,GFP_KERNEL);
a424f8bf 3220 }
1da177e4 3221 } else { /* no room so create dummy domain and NOS string */
fb8c4b14 3222 if (ses->serverDomain)
a424f8bf 3223 kfree(ses->serverDomain);
e915fc49 3224 ses->serverDomain = kzalloc(2, GFP_KERNEL);
cd49b492 3225 kfree(ses->serverNOS);
e915fc49 3226 ses->serverNOS = kzalloc(2, GFP_KERNEL);
1da177e4
LT
3227 }
3228 } else { /* ASCII */
3229 len = strnlen(bcc_ptr, 1024);
50c2f753
SF
3230 if (((long) bcc_ptr + len) -
3231 (long) pByteArea(smb_buffer_response)
63135e08 3232 <= BCC(smb_buffer_response)) {
fb8c4b14 3233 if (ses->serverOS)
a424f8bf 3234 kfree(ses->serverOS);
77159b4d 3235 ses->serverOS = kzalloc(len + 1, GFP_KERNEL);
1da177e4
LT
3236 strncpy(ses->serverOS,bcc_ptr, len);
3237
3238 bcc_ptr += len;
3239 bcc_ptr[0] = 0; /* null terminate the string */
3240 bcc_ptr++;
3241
3242 len = strnlen(bcc_ptr, 1024);
cd49b492 3243 kfree(ses->serverNOS);
50c2f753
SF
3244 ses->serverNOS = kzalloc(len+1,
3245 GFP_KERNEL);
63135e08
SF
3246 strncpy(ses->serverNOS,
3247 bcc_ptr, len);
1da177e4
LT
3248 bcc_ptr += len;
3249 bcc_ptr[0] = 0;
3250 bcc_ptr++;
3251
3252 len = strnlen(bcc_ptr, 1024);
fb8c4b14 3253 if (ses->serverDomain)
a424f8bf 3254 kfree(ses->serverDomain);
63135e08
SF
3255 ses->serverDomain =
3256 kzalloc(len+1,
3257 GFP_KERNEL);
3258 strncpy(ses->serverDomain,
3259 bcc_ptr, len);
1da177e4
LT
3260 bcc_ptr += len;
3261 bcc_ptr[0] = 0;
3262 bcc_ptr++;
3263 } else
6345a3a8 3264 cFYI(1, ("field of length %d "
63135e08 3265 "extends beyond end of smb ",
1da177e4
LT
3266 len));
3267 }
3268 } else {
6345a3a8 3269 cERROR(1, ("Security Blob extends beyond end "
63135e08 3270 "of SMB"));
1da177e4
LT
3271 }
3272 } else {
3273 cERROR(1, ("No session structure passed in."));
3274 }
3275 } else {
6345a3a8 3276 cERROR(1, ("Invalid Word count %d: ",
1da177e4
LT
3277 smb_buffer_response->WordCount));
3278 rc = -EIO;
3279 }
3280
a8a11d39 3281 cifs_buf_release(smb_buffer);
1da177e4
LT
3282
3283 return rc;
3284}
3285
3286int
3287CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
3288 const char *tree, struct cifsTconInfo *tcon,
3289 const struct nls_table *nls_codepage)
3290{
3291 struct smb_hdr *smb_buffer;
3292 struct smb_hdr *smb_buffer_response;
3293 TCONX_REQ *pSMB;
3294 TCONX_RSP *pSMBr;
3295 unsigned char *bcc_ptr;
3296 int rc = 0;
3297 int length;
3298 __u16 count;
3299
3300 if (ses == NULL)
3301 return -EIO;
3302
3303 smb_buffer = cifs_buf_get();
3304 if (smb_buffer == NULL) {
3305 return -ENOMEM;
3306 }
3307 smb_buffer_response = smb_buffer;
3308
3309 header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX,
3310 NULL /*no tid */ , 4 /*wct */ );
1982c344
SF
3311
3312 smb_buffer->Mid = GetNextMid(ses->server);
1da177e4
LT
3313 smb_buffer->Uid = ses->Suid;
3314 pSMB = (TCONX_REQ *) smb_buffer;
3315 pSMBr = (TCONX_RSP *) smb_buffer_response;
3316
3317 pSMB->AndXCommand = 0xFF;
3318 pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO);
1da177e4 3319 bcc_ptr = &pSMB->Password[0];
fb8c4b14 3320 if ((ses->server->secMode) & SECMODE_USER) {
eeac8047 3321 pSMB->PasswordLength = cpu_to_le16(1); /* minimum */
7c7b25bc 3322 *bcc_ptr = 0; /* password is null byte */
eeac8047 3323 bcc_ptr++; /* skip password */
7c7b25bc 3324 /* already aligned so no need to do it below */
eeac8047 3325 } else {
7c7b25bc 3326 pSMB->PasswordLength = cpu_to_le16(CIFS_SESS_KEY_SIZE);
eeac8047
SF
3327 /* BB FIXME add code to fail this if NTLMv2 or Kerberos
3328 specified as required (when that support is added to
3329 the vfs in the future) as only NTLM or the much
7c7b25bc 3330 weaker LANMAN (which we do not send by default) is accepted
eeac8047
SF
3331 by Samba (not sure whether other servers allow
3332 NTLMv2 password here) */
7c7b25bc 3333#ifdef CONFIG_CIFS_WEAK_PW_HASH
50c2f753 3334 if ((extended_security & CIFSSEC_MAY_LANMAN) &&
7c7b25bc
SF
3335 (ses->server->secType == LANMAN))
3336 calc_lanman_hash(ses, bcc_ptr);
3337 else
3338#endif /* CIFS_WEAK_PW_HASH */
eeac8047
SF
3339 SMBNTencrypt(ses->password,
3340 ses->server->cryptKey,
3341 bcc_ptr);
3342
7c7b25bc 3343 bcc_ptr += CIFS_SESS_KEY_SIZE;
fb8c4b14 3344 if (ses->capabilities & CAP_UNICODE) {
7c7b25bc
SF
3345 /* must align unicode strings */
3346 *bcc_ptr = 0; /* null byte password */
3347 bcc_ptr++;
3348 }
eeac8047 3349 }
1da177e4 3350
50c2f753 3351 if (ses->server->secMode &
a878fb22 3352 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
1da177e4
LT
3353 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
3354
3355 if (ses->capabilities & CAP_STATUS32) {
3356 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
3357 }
3358 if (ses->capabilities & CAP_DFS) {
3359 smb_buffer->Flags2 |= SMBFLG2_DFS;
3360 }
3361 if (ses->capabilities & CAP_UNICODE) {
3362 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
3363 length =
50c2f753
SF
3364 cifs_strtoUCS((__le16 *) bcc_ptr, tree,
3365 6 /* max utf8 char length in bytes */ *
a878fb22
SF
3366 (/* server len*/ + 256 /* share len */), nls_codepage);
3367 bcc_ptr += 2 * length; /* convert num 16 bit words to bytes */
1da177e4
LT
3368 bcc_ptr += 2; /* skip trailing null */
3369 } else { /* ASCII */
1da177e4
LT
3370 strcpy(bcc_ptr, tree);
3371 bcc_ptr += strlen(tree) + 1;
3372 }
3373 strcpy(bcc_ptr, "?????");
3374 bcc_ptr += strlen("?????");
3375 bcc_ptr += 1;
3376 count = bcc_ptr - &pSMB->Password[0];
3377 pSMB->hdr.smb_buf_length += count;
3378 pSMB->ByteCount = cpu_to_le16(count);
3379
3380 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length, 0);
3381
3382 /* if (rc) rc = map_smb_to_linux_error(smb_buffer_response); */
3383 /* above now done in SendReceive */
3384 if ((rc == 0) && (tcon != NULL)) {
3385 tcon->tidStatus = CifsGood;
3386 tcon->tid = smb_buffer_response->Tid;
3387 bcc_ptr = pByteArea(smb_buffer_response);
3388 length = strnlen(bcc_ptr, BCC(smb_buffer_response) - 2);
50c2f753 3389 /* skip service field (NB: this field is always ASCII) */
7f8ed420
SF
3390 if (length == 3) {
3391 if ((bcc_ptr[0] == 'I') && (bcc_ptr[1] == 'P') &&
3392 (bcc_ptr[2] == 'C')) {
3393 cFYI(1, ("IPC connection"));
3394 tcon->ipc = 1;
3395 }
3396 } else if (length == 2) {
3397 if ((bcc_ptr[0] == 'A') && (bcc_ptr[1] == ':')) {
3398 /* the most common case */
3399 cFYI(1, ("disk share connection"));
3400 }
3401 }
50c2f753 3402 bcc_ptr += length + 1;
1da177e4
LT
3403 strncpy(tcon->treeName, tree, MAX_TREE_SIZE);
3404 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
3405 length = UniStrnlen((wchar_t *) bcc_ptr, 512);
3406 if ((bcc_ptr + (2 * length)) -
3407 pByteArea(smb_buffer_response) <=
3408 BCC(smb_buffer_response)) {
f99d49ad 3409 kfree(tcon->nativeFileSystem);
1da177e4 3410 tcon->nativeFileSystem =
e915fc49 3411 kzalloc(length + 2, GFP_KERNEL);
88f370a6
SF
3412 if (tcon->nativeFileSystem)
3413 cifs_strfromUCS_le(
3414 tcon->nativeFileSystem,
3415 (__le16 *) bcc_ptr,
3416 length, nls_codepage);
1da177e4
LT
3417 bcc_ptr += 2 * length;
3418 bcc_ptr[0] = 0; /* null terminate the string */
3419 bcc_ptr[1] = 0;
3420 bcc_ptr += 2;
3421 }
50c2f753 3422 /* else do not bother copying these information fields*/
1da177e4
LT
3423 } else {
3424 length = strnlen(bcc_ptr, 1024);
3425 if ((bcc_ptr + length) -
3426 pByteArea(smb_buffer_response) <=
3427 BCC(smb_buffer_response)) {
f99d49ad 3428 kfree(tcon->nativeFileSystem);
1da177e4 3429 tcon->nativeFileSystem =
e915fc49 3430 kzalloc(length + 1, GFP_KERNEL);
88f370a6
SF
3431 if (tcon->nativeFileSystem)
3432 strncpy(tcon->nativeFileSystem, bcc_ptr,
3433 length);
1da177e4 3434 }
50c2f753 3435 /* else do not bother copying these information fields*/
1da177e4 3436 }
fb8c4b14 3437 if ((smb_buffer_response->WordCount == 3) ||
1a4e15a0
SF
3438 (smb_buffer_response->WordCount == 7))
3439 /* field is in same location */
3979877e
SF
3440 tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
3441 else
3442 tcon->Flags = 0;
1da177e4
LT
3443 cFYI(1, ("Tcon flags: 0x%x ", tcon->Flags));
3444 } else if ((rc == 0) && tcon == NULL) {
50c2f753 3445 /* all we need to save for IPC$ connection */
1da177e4
LT
3446 ses->ipc_tid = smb_buffer_response->Tid;
3447 }
3448
a8a11d39 3449 cifs_buf_release(smb_buffer);
1da177e4
LT
3450 return rc;
3451}
3452
3453int
3454cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
3455{
3456 int rc = 0;
3457 int xid;
3458 struct cifsSesInfo *ses = NULL;
3459 struct task_struct *cifsd_task;
50c2f753 3460 char *tmp;
1da177e4
LT
3461
3462 xid = GetXid();
3463
3464 if (cifs_sb->tcon) {
3465 ses = cifs_sb->tcon->ses; /* save ptr to ses before delete tcon!*/
3466 rc = CIFSSMBTDis(xid, cifs_sb->tcon);
3467 if (rc == -EBUSY) {
3468 FreeXid(xid);
3469 return 0;
3470 }
3471 tconInfoFree(cifs_sb->tcon);
3472 if ((ses) && (ses->server)) {
3473 /* save off task so we do not refer to ses later */
3474 cifsd_task = ses->server->tsk;
3475 cFYI(1, ("About to do SMBLogoff "));
3476 rc = CIFSSMBLogoff(xid, ses);
3477 if (rc == -EBUSY) {
3478 FreeXid(xid);
3479 return 0;
3480 } else if (rc == -ESHUTDOWN) {
467a8f8d 3481 cFYI(1, ("Waking up socket by sending signal"));
f7f7c31c 3482 if (cifsd_task) {
50c2f753 3483 force_sig(SIGKILL, cifsd_task);
aaf737ad 3484 kthread_stop(cifsd_task);
f191401f 3485 }
1da177e4
LT
3486 rc = 0;
3487 } /* else - we have an smb session
3488 left on this socket do not kill cifsd */
3489 } else
3490 cFYI(1, ("No session or bad tcon"));
3491 }
50c2f753 3492
1da177e4 3493 cifs_sb->tcon = NULL;
2fe87f02
SF
3494 tmp = cifs_sb->prepath;
3495 cifs_sb->prepathlen = 0;
3496 cifs_sb->prepath = NULL;
3497 kfree(tmp);
041e0e3b
NA
3498 if (ses)
3499 schedule_timeout_interruptible(msecs_to_jiffies(500));
1da177e4
LT
3500 if (ses)
3501 sesInfoFree(ses);
3502
3503 FreeXid(xid);
50c2f753
SF
3504 return rc; /* BB check if we should always return zero here */
3505}
1da177e4
LT
3506
3507int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
50c2f753 3508 struct nls_table *nls_info)
1da177e4
LT
3509{
3510 int rc = 0;
7c7b25bc 3511 char ntlm_session_key[CIFS_SESS_KEY_SIZE];
1da177e4 3512 int ntlmv2_flag = FALSE;
ad009ac9 3513 int first_time = 0;
1da177e4
LT
3514
3515 /* what if server changes its buffer size after dropping the session? */
fb8c4b14 3516 if (pSesInfo->server->maxBuf == 0) /* no need to send on reconnect */ {
1da177e4 3517 rc = CIFSSMBNegotiate(xid, pSesInfo);
fb8c4b14 3518 if (rc == -EAGAIN) /* retry only once on 1st time connection */ {
1da177e4 3519 rc = CIFSSMBNegotiate(xid, pSesInfo);
50c2f753 3520 if (rc == -EAGAIN)
1da177e4
LT
3521 rc = -EHOSTDOWN;
3522 }
fb8c4b14 3523 if (rc == 0) {
1da177e4 3524 spin_lock(&GlobalMid_Lock);
fb8c4b14 3525 if (pSesInfo->server->tcpStatus != CifsExiting)
1da177e4
LT
3526 pSesInfo->server->tcpStatus = CifsGood;
3527 else
3528 rc = -EHOSTDOWN;
3529 spin_unlock(&GlobalMid_Lock);
3530
3531 }
ad009ac9 3532 first_time = 1;
1da177e4
LT
3533 }
3534 if (!rc) {
9ac00b7d 3535 pSesInfo->flags = 0;
1da177e4 3536 pSesInfo->capabilities = pSesInfo->server->capabilities;
fb8c4b14 3537 if (linuxExtEnabled == 0)
1da177e4 3538 pSesInfo->capabilities &= (~CAP_UNIX);
ad009ac9 3539 /* pSesInfo->sequence_number = 0;*/
50c2f753
SF
3540 cFYI(1,
3541 ("Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d",
1da177e4
LT
3542 pSesInfo->server->secMode,
3543 pSesInfo->server->capabilities,
175ec9e1 3544 pSesInfo->server->timeAdj));
fb8c4b14 3545 if (experimEnabled < 2)
3979877e
SF
3546 rc = CIFS_SessSetup(xid, pSesInfo,
3547 first_time, nls_info);
189acaae 3548 else if (extended_security
50c2f753 3549 && (pSesInfo->capabilities
175ec9e1 3550 & CAP_EXTENDED_SECURITY)
1da177e4 3551 && (pSesInfo->server->secType == NTLMSSP)) {
189acaae 3552 rc = -EOPNOTSUPP;
1da177e4
LT
3553 } else if (extended_security
3554 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
3555 && (pSesInfo->server->secType == RawNTLMSSP)) {
5815449d 3556 cFYI(1, ("NTLMSSP sesssetup"));
1da177e4
LT
3557 rc = CIFSNTLMSSPNegotiateSessSetup(xid,
3558 pSesInfo,
3559 &ntlmv2_flag,
3560 nls_info);
3561 if (!rc) {
fb8c4b14 3562 if (ntlmv2_flag) {
50c2f753 3563 char *v2_response;
467a8f8d 3564 cFYI(1, ("more secure NTLM ver2 hash"));
50c2f753 3565 if (CalcNTLMv2_partial_mac_key(pSesInfo,
1da177e4
LT
3566 nls_info)) {
3567 rc = -ENOMEM;
3568 goto ss_err_exit;
3569 } else
3570 v2_response = kmalloc(16 + 64 /* blob */, GFP_KERNEL);
fb8c4b14 3571 if (v2_response) {
50c2f753
SF
3572 CalcNTLMv2_response(pSesInfo,
3573 v2_response);
fb8c4b14 3574 /* if (first_time)
50c2f753
SF
3575 cifs_calculate_ntlmv2_mac_key(
3576 pSesInfo->server->mac_signing_key,
3577 response, ntlm_session_key,*/
1da177e4
LT
3578 kfree(v2_response);
3579 /* BB Put dummy sig in SessSetup PDU? */
3580 } else {
3581 rc = -ENOMEM;
3582 goto ss_err_exit;
3583 }
3584
3585 } else {
3586 SMBNTencrypt(pSesInfo->password,
3587 pSesInfo->server->cryptKey,
3588 ntlm_session_key);
3589
fb8c4b14 3590 if (first_time)
ad009ac9 3591 cifs_calculate_mac_key(
b609f06a 3592 &pSesInfo->server->mac_signing_key,
ad009ac9
SF
3593 ntlm_session_key,
3594 pSesInfo->password);
1da177e4
LT
3595 }
3596 /* for better security the weaker lanman hash not sent
3597 in AuthSessSetup so we no longer calculate it */
3598
3599 rc = CIFSNTLMSSPAuthSessSetup(xid,
3600 pSesInfo,
3601 ntlm_session_key,
3602 ntlmv2_flag,
3603 nls_info);
3604 }
3605 } else { /* old style NTLM 0.12 session setup */
3606 SMBNTencrypt(pSesInfo->password,
3607 pSesInfo->server->cryptKey,
3608 ntlm_session_key);
3609
fb8c4b14 3610 if (first_time)
ad009ac9 3611 cifs_calculate_mac_key(
b609f06a 3612 &pSesInfo->server->mac_signing_key,
ad009ac9
SF
3613 ntlm_session_key, pSesInfo->password);
3614
1da177e4
LT
3615 rc = CIFSSessSetup(xid, pSesInfo,
3616 ntlm_session_key, nls_info);
3617 }
3618 if (rc) {
fb8c4b14 3619 cERROR(1, ("Send error in SessSetup = %d", rc));
1da177e4 3620 } else {
467a8f8d 3621 cFYI(1, ("CIFS Session Established successfully"));
1da177e4
LT
3622 pSesInfo->status = CifsGood;
3623 }
3624 }
3625ss_err_exit:
3626 return rc;
3627}
3628