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