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