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