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