1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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/pagemap.h>
27#include <linux/ctype.h>
28#include <linux/utsname.h>
29#include <linux/mempool.h>
30#include <linux/delay.h>
31#include <linux/completion.h>
32#include <linux/kthread.h>
33#include <linux/pagevec.h>
34#include <linux/freezer.h>
35#include <linux/namei.h>
36#include <asm/uaccess.h>
37#include <asm/processor.h>
38#include <linux/inet.h>
39#include <net/ipv6.h>
40#include "cifspdu.h"
41#include "cifsglob.h"
42#include "cifsproto.h"
43#include "cifs_unicode.h"
44#include "cifs_debug.h"
45#include "cifs_fs_sb.h"
46#include "ntlmssp.h"
47#include "nterr.h"
48#include "rfc1002pdu.h"
49#include "cn_cifs.h"
50
51#define CIFS_PORT 445
52#define RFC1001_PORT 139
53
54extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8,
55 unsigned char *p24);
56
57extern mempool_t *cifs_req_poolp;
58
59struct smb_vol {
60 char *username;
61 char *password;
62 char *domainname;
63 char *UNC;
64 char *UNCip;
65 char *iocharset;
66 char source_rfc1001_name[16];
67 char target_rfc1001_name[16];
68 uid_t linux_uid;
69 gid_t linux_gid;
70 mode_t file_mode;
71 mode_t dir_mode;
72 unsigned secFlg;
73 bool retry:1;
74 bool intr:1;
75 bool setuids:1;
76 bool override_uid:1;
77 bool override_gid:1;
78 bool dynperm:1;
79 bool noperm:1;
80 bool no_psx_acl:1;
81 bool cifs_acl:1;
82 bool no_xattr:1;
83 bool server_ino:1;
84 bool direct_io:1;
85 bool remap:1;
86 bool posix_paths:1;
87 bool no_linux_ext:1;
88 bool sfu_emul:1;
89 bool nullauth:1;
90 bool nocase:1;
91 bool nobrl:1;
92 bool mand_lock:1;
93 bool seal:1;
94 bool nodfs:1;
95 bool local_lease:1;
96 bool noblocksnd:1;
97 bool noautotune:1;
98 bool nostrictsync:1;
99 unsigned int rsize;
100 unsigned int wsize;
101 unsigned int sockopt;
102 unsigned short int port;
103 char *prepath;
104};
105
106static int ipv4_connect(struct TCP_Server_Info *server);
107static int ipv6_connect(struct TCP_Server_Info *server);
108
109
110
111
112
113
114
115
116
117static int
118cifs_reconnect(struct TCP_Server_Info *server)
119{
120 int rc = 0;
121 struct list_head *tmp, *tmp2;
122 struct cifsSesInfo *ses;
123 struct cifsTconInfo *tcon;
124 struct mid_q_entry *mid_entry;
125
126 spin_lock(&GlobalMid_Lock);
127 if (server->tcpStatus == CifsExiting) {
128
129
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
140
141 read_lock(&cifs_tcp_ses_lock);
142 list_for_each(tmp, &server->smb_ses_list) {
143 ses = list_entry(tmp, struct cifsSesInfo, smb_ses_list);
144 ses->need_reconnect = true;
145 ses->ipc_tid = 0;
146 list_for_each(tmp2, &ses->tcon_list) {
147 tcon = list_entry(tmp2, struct cifsTconInfo, tcon_list);
148 tcon->need_reconnect = true;
149 }
150 }
151 read_unlock(&cifs_tcp_ses_lock);
152
153 mutex_lock(&server->srv_mutex);
154 if (server->ssocket) {
155 cFYI(1, ("State: 0x%x Flags: 0x%lx", server->ssocket->state,
156 server->ssocket->flags));
157 kernel_sock_shutdown(server->ssocket, SHUT_WR);
158 cFYI(1, ("Post shutdown state: 0x%x Flags: 0x%lx",
159 server->ssocket->state,
160 server->ssocket->flags));
161 sock_release(server->ssocket);
162 server->ssocket = NULL;
163 }
164
165 spin_lock(&GlobalMid_Lock);
166 list_for_each(tmp, &server->pending_mid_q) {
167 mid_entry = list_entry(tmp, struct
168 mid_q_entry,
169 qhead);
170 if (mid_entry->midState == MID_REQUEST_SUBMITTED) {
171
172
173
174
175 mid_entry->midState = MID_RETRY_NEEDED;
176 }
177 }
178 spin_unlock(&GlobalMid_Lock);
179 mutex_unlock(&server->srv_mutex);
180
181 while ((server->tcpStatus != CifsExiting) &&
182 (server->tcpStatus != CifsGood)) {
183 try_to_freeze();
184 if (server->addr.sockAddr6.sin6_family == AF_INET6)
185 rc = ipv6_connect(server);
186 else
187 rc = ipv4_connect(server);
188 if (rc) {
189 cFYI(1, ("reconnect error %d", rc));
190 msleep(3000);
191 } else {
192 atomic_inc(&tcpSesReconnectCount);
193 spin_lock(&GlobalMid_Lock);
194 if (server->tcpStatus != CifsExiting)
195 server->tcpStatus = CifsGood;
196 server->sequence_number = 0;
197 spin_unlock(&GlobalMid_Lock);
198
199 wake_up(&server->response_q);
200 }
201 }
202 return rc;
203}
204
205
206
207
208
209
210
211
212static int check2ndT2(struct smb_hdr *pSMB, unsigned int maxBufSize)
213{
214 struct smb_t2_rsp *pSMBt;
215 int total_data_size;
216 int data_in_this_rsp;
217 int remaining;
218
219 if (pSMB->Command != SMB_COM_TRANSACTION2)
220 return 0;
221
222
223
224 if (pSMB->WordCount != 10) {
225 cFYI(1, ("invalid transact2 word count"));
226 return -EINVAL;
227 }
228
229 pSMBt = (struct smb_t2_rsp *)pSMB;
230
231 total_data_size = le16_to_cpu(pSMBt->t2_rsp.TotalDataCount);
232 data_in_this_rsp = le16_to_cpu(pSMBt->t2_rsp.DataCount);
233
234 remaining = total_data_size - data_in_this_rsp;
235
236 if (remaining == 0)
237 return 0;
238 else if (remaining < 0) {
239 cFYI(1, ("total data %d smaller than data in frame %d",
240 total_data_size, data_in_this_rsp));
241 return -EINVAL;
242 } else {
243 cFYI(1, ("missing %d bytes from transact2, check next response",
244 remaining));
245 if (total_data_size > maxBufSize) {
246 cERROR(1, ("TotalDataSize %d is over maximum buffer %d",
247 total_data_size, maxBufSize));
248 return -EINVAL;
249 }
250 return remaining;
251 }
252}
253
254static int coalesce_t2(struct smb_hdr *psecond, struct smb_hdr *pTargetSMB)
255{
256 struct smb_t2_rsp *pSMB2 = (struct smb_t2_rsp *)psecond;
257 struct smb_t2_rsp *pSMBt = (struct smb_t2_rsp *)pTargetSMB;
258 int total_data_size;
259 int total_in_buf;
260 int remaining;
261 int total_in_buf2;
262 char *data_area_of_target;
263 char *data_area_of_buf2;
264 __u16 byte_count;
265
266 total_data_size = le16_to_cpu(pSMBt->t2_rsp.TotalDataCount);
267
268 if (total_data_size != le16_to_cpu(pSMB2->t2_rsp.TotalDataCount)) {
269 cFYI(1, ("total data size of primary and secondary t2 differ"));
270 }
271
272 total_in_buf = le16_to_cpu(pSMBt->t2_rsp.DataCount);
273
274 remaining = total_data_size - total_in_buf;
275
276 if (remaining < 0)
277 return -EINVAL;
278
279 if (remaining == 0)
280 return 0;
281
282 total_in_buf2 = le16_to_cpu(pSMB2->t2_rsp.DataCount);
283 if (remaining < total_in_buf2) {
284 cFYI(1, ("transact2 2nd response contains too much data"));
285 }
286
287
288 data_area_of_target = (char *)&pSMBt->hdr.Protocol +
289 le16_to_cpu(pSMBt->t2_rsp.DataOffset);
290
291
292 data_area_of_buf2 = (char *) &pSMB2->hdr.Protocol +
293 le16_to_cpu(pSMB2->t2_rsp.DataOffset);
294
295 data_area_of_target += total_in_buf;
296
297
298 memcpy(data_area_of_target, data_area_of_buf2, total_in_buf2);
299 total_in_buf += total_in_buf2;
300 pSMBt->t2_rsp.DataCount = cpu_to_le16(total_in_buf);
301 byte_count = le16_to_cpu(BCC_LE(pTargetSMB));
302 byte_count += total_in_buf2;
303 BCC_LE(pTargetSMB) = cpu_to_le16(byte_count);
304
305 byte_count = pTargetSMB->smb_buf_length;
306 byte_count += total_in_buf2;
307
308
309
310 pTargetSMB->smb_buf_length = byte_count;
311
312 if (remaining == total_in_buf2) {
313 cFYI(1, ("found the last secondary response"));
314 return 0;
315 } else
316 return 1;
317
318}
319
320static int
321cifs_demultiplex_thread(struct TCP_Server_Info *server)
322{
323 int length;
324 unsigned int pdu_length, total_read;
325 struct smb_hdr *smb_buffer = NULL;
326 struct smb_hdr *bigbuf = NULL;
327 struct smb_hdr *smallbuf = NULL;
328 struct msghdr smb_msg;
329 struct kvec iov;
330 struct socket *csocket = server->ssocket;
331 struct list_head *tmp;
332 struct cifsSesInfo *ses;
333 struct task_struct *task_to_wake = NULL;
334 struct mid_q_entry *mid_entry;
335 char temp;
336 bool isLargeBuf = false;
337 bool isMultiRsp;
338 int reconnect;
339
340 current->flags |= PF_MEMALLOC;
341 cFYI(1, ("Demultiplex PID: %d", task_pid_nr(current)));
342
343 length = atomic_inc_return(&tcpSesAllocCount);
344 if (length > 1)
345 mempool_resize(cifs_req_poolp, length + cifs_min_rcv,
346 GFP_KERNEL);
347
348 set_freezable();
349 while (server->tcpStatus != CifsExiting) {
350 if (try_to_freeze())
351 continue;
352 if (bigbuf == NULL) {
353 bigbuf = cifs_buf_get();
354 if (!bigbuf) {
355 cERROR(1, ("No memory for large SMB response"));
356 msleep(3000);
357
358 continue;
359 }
360 } else if (isLargeBuf) {
361
362 memset(bigbuf, 0, sizeof(struct smb_hdr));
363 }
364
365 if (smallbuf == NULL) {
366 smallbuf = cifs_small_buf_get();
367 if (!smallbuf) {
368 cERROR(1, ("No memory for SMB response"));
369 msleep(1000);
370
371 continue;
372 }
373
374 } else
375 memset(smallbuf, 0, sizeof(struct smb_hdr));
376
377 isLargeBuf = false;
378 isMultiRsp = false;
379 smb_buffer = smallbuf;
380 iov.iov_base = smb_buffer;
381 iov.iov_len = 4;
382 smb_msg.msg_control = NULL;
383 smb_msg.msg_controllen = 0;
384 pdu_length = 4;
385incomplete_rcv:
386 length =
387 kernel_recvmsg(csocket, &smb_msg,
388 &iov, 1, pdu_length, 0 );
389
390 if (server->tcpStatus == CifsExiting) {
391 break;
392 } else if (server->tcpStatus == CifsNeedReconnect) {
393 cFYI(1, ("Reconnect after server stopped responding"));
394 cifs_reconnect(server);
395 cFYI(1, ("call to reconnect done"));
396 csocket = server->ssocket;
397 continue;
398 } else if ((length == -ERESTARTSYS) || (length == -EAGAIN)) {
399 msleep(1);
400
401
402 if (pdu_length < 4) {
403 iov.iov_base = (4 - pdu_length) +
404 (char *)smb_buffer;
405 iov.iov_len = pdu_length;
406 smb_msg.msg_control = NULL;
407 smb_msg.msg_controllen = 0;
408 goto incomplete_rcv;
409 } else
410 continue;
411 } else if (length <= 0) {
412 if (server->tcpStatus == CifsNew) {
413 cFYI(1, ("tcp session abend after SMBnegprot"));
414
415
416
417
418 break;
419 }
420 if (!try_to_freeze() && (length == -EINTR)) {
421 cFYI(1, ("cifsd thread killed"));
422 break;
423 }
424 cFYI(1, ("Reconnect after unexpected peek error %d",
425 length));
426 cifs_reconnect(server);
427 csocket = server->ssocket;
428 wake_up(&server->response_q);
429 continue;
430 } else if (length < pdu_length) {
431 cFYI(1, ("requested %d bytes but only got %d bytes",
432 pdu_length, length));
433 pdu_length -= length;
434 msleep(1);
435 goto incomplete_rcv;
436 }
437
438
439
440
441
442
443
444 temp = *((char *) smb_buffer);
445
446
447
448
449 pdu_length = be32_to_cpu((__force __be32)smb_buffer->smb_buf_length);
450 smb_buffer->smb_buf_length = pdu_length;
451
452 cFYI(1, ("rfc1002 length 0x%x", pdu_length+4));
453
454 if (temp == (char) RFC1002_SESSION_KEEP_ALIVE) {
455 continue;
456 } else if (temp == (char)RFC1002_POSITIVE_SESSION_RESPONSE) {
457 cFYI(1, ("Good RFC 1002 session rsp"));
458 continue;
459 } else if (temp == (char)RFC1002_NEGATIVE_SESSION_RESPONSE) {
460
461
462 cFYI(1, ("Negative RFC1002 Session Response Error 0x%x)",
463 pdu_length));
464 if (server->tcpStatus == CifsNew) {
465
466
467
468 break;
469 } else {
470
471
472 msleep(1000);
473
474
475
476
477
478 server->addr.sockAddr.sin_port =
479 htons(CIFS_PORT);
480 cifs_reconnect(server);
481 csocket = server->ssocket;
482 wake_up(&server->response_q);
483 continue;
484 }
485 } else if (temp != (char) 0) {
486 cERROR(1, ("Unknown RFC 1002 frame"));
487 cifs_dump_mem(" Received Data: ", (char *)smb_buffer,
488 length);
489 cifs_reconnect(server);
490 csocket = server->ssocket;
491 continue;
492 }
493
494
495 if ((pdu_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) ||
496 (pdu_length < sizeof(struct smb_hdr) - 1 - 4)) {
497 cERROR(1, ("Invalid size SMB length %d pdu_length %d",
498 length, pdu_length+4));
499 cifs_reconnect(server);
500 csocket = server->ssocket;
501 wake_up(&server->response_q);
502 continue;
503 }
504
505
506 reconnect = 0;
507
508 if (pdu_length > MAX_CIFS_SMALL_BUFFER_SIZE - 4) {
509 isLargeBuf = true;
510 memcpy(bigbuf, smallbuf, 4);
511 smb_buffer = bigbuf;
512 }
513 length = 0;
514 iov.iov_base = 4 + (char *)smb_buffer;
515 iov.iov_len = pdu_length;
516 for (total_read = 0; total_read < pdu_length;
517 total_read += length) {
518 length = kernel_recvmsg(csocket, &smb_msg, &iov, 1,
519 pdu_length - total_read, 0);
520 if ((server->tcpStatus == CifsExiting) ||
521 (length == -EINTR)) {
522
523 reconnect = 2;
524 break;
525 } else if (server->tcpStatus == CifsNeedReconnect) {
526 cifs_reconnect(server);
527 csocket = server->ssocket;
528
529
530 reconnect = 1;
531 break;
532 } else if ((length == -ERESTARTSYS) ||
533 (length == -EAGAIN)) {
534 msleep(1);
535
536
537
538 length = 0;
539 continue;
540 } else if (length <= 0) {
541 cERROR(1, ("Received no data, expecting %d",
542 pdu_length - total_read));
543 cifs_reconnect(server);
544 csocket = server->ssocket;
545 reconnect = 1;
546 break;
547 }
548 }
549 if (reconnect == 2)
550 break;
551 else if (reconnect == 1)
552 continue;
553
554 length += 4;
555
556
557 dump_smb(smb_buffer, length);
558 if (checkSMB(smb_buffer, smb_buffer->Mid, total_read+4)) {
559 cifs_dump_mem("Bad SMB: ", smb_buffer, 48);
560 continue;
561 }
562
563
564 task_to_wake = NULL;
565 spin_lock(&GlobalMid_Lock);
566 list_for_each(tmp, &server->pending_mid_q) {
567 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
568
569 if ((mid_entry->mid == smb_buffer->Mid) &&
570 (mid_entry->midState == MID_REQUEST_SUBMITTED) &&
571 (mid_entry->command == smb_buffer->Command)) {
572 if (check2ndT2(smb_buffer,server->maxBuf) > 0) {
573
574 isMultiRsp = true;
575 if (mid_entry->resp_buf) {
576
577 if (coalesce_t2(smb_buffer,
578 mid_entry->resp_buf)) {
579 mid_entry->multiRsp =
580 true;
581 break;
582 } else {
583
584 mid_entry->multiEnd =
585 true;
586 goto multi_t2_fnd;
587 }
588 } else {
589 if (!isLargeBuf) {
590 cERROR(1,("1st trans2 resp needs bigbuf"));
591
592
593 } else {
594
595 mid_entry->resp_buf =
596 smb_buffer;
597 mid_entry->largeBuf =
598 true;
599 bigbuf = NULL;
600 }
601 }
602 break;
603 }
604 mid_entry->resp_buf = smb_buffer;
605 mid_entry->largeBuf = isLargeBuf;
606multi_t2_fnd:
607 task_to_wake = mid_entry->tsk;
608 mid_entry->midState = MID_RESPONSE_RECEIVED;
609#ifdef CONFIG_CIFS_STATS2
610 mid_entry->when_received = jiffies;
611#endif
612
613
614
615 server->lstrp = jiffies;
616 break;
617 }
618 }
619 spin_unlock(&GlobalMid_Lock);
620 if (task_to_wake) {
621
622 if (!isMultiRsp) {
623
624 if (isLargeBuf)
625 bigbuf = NULL;
626 else
627 smallbuf = NULL;
628 }
629 wake_up_process(task_to_wake);
630 } else if (!is_valid_oplock_break(smb_buffer, server) &&
631 !isMultiRsp) {
632 cERROR(1, ("No task to wake, unknown frame received! "
633 "NumMids %d", midCount.counter));
634 cifs_dump_mem("Received Data is: ", (char *)smb_buffer,
635 sizeof(struct smb_hdr));
636#ifdef CONFIG_CIFS_DEBUG2
637 cifs_dump_detail(smb_buffer);
638 cifs_dump_mids(server);
639#endif
640
641 }
642 }
643
644
645 write_lock(&cifs_tcp_ses_lock);
646 list_del_init(&server->tcp_ses_list);
647 write_unlock(&cifs_tcp_ses_lock);
648
649 spin_lock(&GlobalMid_Lock);
650 server->tcpStatus = CifsExiting;
651 spin_unlock(&GlobalMid_Lock);
652 wake_up_all(&server->response_q);
653
654
655
656
657 spin_lock(&GlobalMid_Lock);
658 if (atomic_read(&server->inFlight) >= cifs_max_pending)
659 atomic_set(&server->inFlight, cifs_max_pending - 1);
660
661
662 spin_unlock(&GlobalMid_Lock);
663
664
665
666
667
668 wake_up_all(&server->request_q);
669
670 msleep(125);
671
672 if (server->ssocket) {
673 sock_release(csocket);
674 server->ssocket = NULL;
675 }
676
677 cifs_buf_release(bigbuf);
678 if (smallbuf)
679 cifs_small_buf_release(smallbuf);
680
681
682
683
684
685 read_lock(&cifs_tcp_ses_lock);
686 if (list_empty(&server->pending_mid_q)) {
687
688
689 list_for_each(tmp, &server->smb_ses_list) {
690 ses = list_entry(tmp, struct cifsSesInfo,
691 smb_ses_list);
692 ses->status = CifsExiting;
693 ses->server = NULL;
694 }
695 read_unlock(&cifs_tcp_ses_lock);
696 } else {
697
698
699
700 list_for_each(tmp, &server->smb_ses_list) {
701 ses = list_entry(tmp, struct cifsSesInfo,
702 smb_ses_list);
703 ses->status = CifsExiting;
704 }
705
706 spin_lock(&GlobalMid_Lock);
707 list_for_each(tmp, &server->pending_mid_q) {
708 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
709 if (mid_entry->midState == MID_REQUEST_SUBMITTED) {
710 cFYI(1, ("Clearing Mid 0x%x - waking up ",
711 mid_entry->mid));
712 task_to_wake = mid_entry->tsk;
713 if (task_to_wake)
714 wake_up_process(task_to_wake);
715 }
716 }
717 spin_unlock(&GlobalMid_Lock);
718 read_unlock(&cifs_tcp_ses_lock);
719
720 msleep(125);
721 }
722
723 if (!list_empty(&server->pending_mid_q)) {
724
725
726
727
728
729
730 cFYI(1, ("Wait for exit from demultiplex thread"));
731 msleep(46000);
732
733
734 }
735
736
737
738
739
740
741 read_lock(&cifs_tcp_ses_lock);
742 list_for_each(tmp, &server->smb_ses_list) {
743 ses = list_entry(tmp, struct cifsSesInfo, smb_ses_list);
744 ses->server = NULL;
745 }
746 read_unlock(&cifs_tcp_ses_lock);
747
748 kfree(server->hostname);
749 task_to_wake = xchg(&server->tsk, NULL);
750 kfree(server);
751
752 length = atomic_dec_return(&tcpSesAllocCount);
753 if (length > 0)
754 mempool_resize(cifs_req_poolp, length + cifs_min_rcv,
755 GFP_KERNEL);
756
757
758 if (!task_to_wake) {
759 set_current_state(TASK_INTERRUPTIBLE);
760 while (!signal_pending(current)) {
761 schedule();
762 set_current_state(TASK_INTERRUPTIBLE);
763 }
764 set_current_state(TASK_RUNNING);
765 }
766
767 module_put_and_exit(0);
768}
769
770
771static char *
772extract_hostname(const char *unc)
773{
774 const char *src;
775 char *dst, *delim;
776 unsigned int len;
777
778
779
780 src = unc + 2;
781
782
783 delim = strchr(src, '\\');
784 if (!delim)
785 return ERR_PTR(-EINVAL);
786
787 len = delim - src;
788 dst = kmalloc((len + 1), GFP_KERNEL);
789 if (dst == NULL)
790 return ERR_PTR(-ENOMEM);
791
792 memcpy(dst, src, len);
793 dst[len] = '\0';
794
795 return dst;
796}
797
798static int
799cifs_parse_mount_options(char *options, const char *devname,
800 struct smb_vol *vol)
801{
802 char *value;
803 char *data;
804 unsigned int temp_len, i, j;
805 char separator[2];
806 short int override_uid = -1;
807 short int override_gid = -1;
808 bool uid_specified = false;
809 bool gid_specified = false;
810
811 separator[0] = ',';
812 separator[1] = 0;
813
814 if (Local_System_Name[0] != 0)
815 memcpy(vol->source_rfc1001_name, Local_System_Name, 15);
816 else {
817 char *nodename = utsname()->nodename;
818 int n = strnlen(nodename, 15);
819 memset(vol->source_rfc1001_name, 0x20, 15);
820 for (i = 0; i < n; i++) {
821
822
823
824 vol->source_rfc1001_name[i] = toupper(nodename[i]);
825 }
826 }
827 vol->source_rfc1001_name[15] = 0;
828
829
830 vol->target_rfc1001_name[0] = 0;
831 vol->linux_uid = current_uid();
832 vol->linux_gid = current_gid();
833
834
835 vol->dir_mode = vol->file_mode = S_IRUGO | S_IXUGO | S_IWUSR;
836
837
838
839 vol->posix_paths = 1;
840
841 vol->server_ino = 1;
842
843 if (!options)
844 return 1;
845
846 if (strncmp(options, "sep=", 4) == 0) {
847 if (options[4] != 0) {
848 separator[0] = options[4];
849 options += 5;
850 } else {
851 cFYI(1, ("Null separator not allowed"));
852 }
853 }
854
855 while ((data = strsep(&options, separator)) != NULL) {
856 if (!*data)
857 continue;
858 if ((value = strchr(data, '=')) != NULL)
859 *value++ = '\0';
860
861
862 if (strnicmp(data, "user_xattr", 10) == 0) {
863 vol->no_xattr = 0;
864 } else if (strnicmp(data, "nouser_xattr", 12) == 0) {
865 vol->no_xattr = 1;
866 } else if (strnicmp(data, "user", 4) == 0) {
867 if (!value) {
868 printk(KERN_WARNING
869 "CIFS: invalid or missing username\n");
870 return 1;
871 } else if (!*value) {
872
873 vol->nullauth = 1;
874 }
875 if (strnlen(value, 200) < 200) {
876 vol->username = value;
877 } else {
878 printk(KERN_WARNING "CIFS: username too long\n");
879 return 1;
880 }
881 } else if (strnicmp(data, "pass", 4) == 0) {
882 if (!value) {
883 vol->password = NULL;
884 continue;
885 } else if (value[0] == 0) {
886
887
888
889
890 if (value[1] != separator[0]) {
891 vol->password = NULL;
892 continue;
893 }
894 }
895 temp_len = strlen(value);
896
897
898
899
900
901
902
903
904
905
906
907
908
909 if ((value[temp_len] == 0) &&
910 (value[temp_len+1] == separator[0])) {
911
912 value[temp_len] = separator[0];
913 temp_len += 2;
914 while (value[temp_len] != 0) {
915 if (value[temp_len] == separator[0]) {
916 if (value[temp_len+1] ==
917 separator[0]) {
918
919 temp_len++;
920 } else {
921
922
923 break;
924 }
925 }
926 temp_len++;
927 }
928 if (value[temp_len] == 0) {
929 options = NULL;
930 } else {
931 value[temp_len] = 0;
932
933 options = value + temp_len + 1;
934 }
935
936
937
938 vol->password = kzalloc(temp_len, GFP_KERNEL);
939 if (vol->password == NULL) {
940 printk(KERN_WARNING "CIFS: no memory "
941 "for password\n");
942 return 1;
943 }
944 for (i = 0, j = 0; i < temp_len; i++, j++) {
945 vol->password[j] = value[i];
946 if (value[i] == separator[0]
947 && value[i+1] == separator[0]) {
948
949 i++;
950 }
951 }
952 vol->password[j] = 0;
953 } else {
954 vol->password = kzalloc(temp_len+1, GFP_KERNEL);
955 if (vol->password == NULL) {
956 printk(KERN_WARNING "CIFS: no memory "
957 "for password\n");
958 return 1;
959 }
960 strcpy(vol->password, value);
961 }
962 } else if (!strnicmp(data, "ip", 2) ||
963 !strnicmp(data, "addr", 4)) {
964 if (!value || !*value) {
965 vol->UNCip = NULL;
966 } else if (strnlen(value, INET6_ADDRSTRLEN) <
967 INET6_ADDRSTRLEN) {
968 vol->UNCip = value;
969 } else {
970 printk(KERN_WARNING "CIFS: ip address "
971 "too long\n");
972 return 1;
973 }
974 } else if (strnicmp(data, "sec", 3) == 0) {
975 if (!value || !*value) {
976 cERROR(1, ("no security value specified"));
977 continue;
978 } else if (strnicmp(value, "krb5i", 5) == 0) {
979 vol->secFlg |= CIFSSEC_MAY_KRB5 |
980 CIFSSEC_MUST_SIGN;
981 } else if (strnicmp(value, "krb5p", 5) == 0) {
982
983
984 cERROR(1, ("Krb5 cifs privacy not supported"));
985 return 1;
986 } else if (strnicmp(value, "krb5", 4) == 0) {
987 vol->secFlg |= CIFSSEC_MAY_KRB5;
988#ifdef CONFIG_CIFS_EXPERIMENTAL
989 } else if (strnicmp(value, "ntlmsspi", 8) == 0) {
990 vol->secFlg |= CIFSSEC_MAY_NTLMSSP |
991 CIFSSEC_MUST_SIGN;
992 } else if (strnicmp(value, "ntlmssp", 7) == 0) {
993 vol->secFlg |= CIFSSEC_MAY_NTLMSSP;
994#endif
995 } else if (strnicmp(value, "ntlmv2i", 7) == 0) {
996 vol->secFlg |= CIFSSEC_MAY_NTLMV2 |
997 CIFSSEC_MUST_SIGN;
998 } else if (strnicmp(value, "ntlmv2", 6) == 0) {
999 vol->secFlg |= CIFSSEC_MAY_NTLMV2;
1000 } else if (strnicmp(value, "ntlmi", 5) == 0) {
1001 vol->secFlg |= CIFSSEC_MAY_NTLM |
1002 CIFSSEC_MUST_SIGN;
1003 } else if (strnicmp(value, "ntlm", 4) == 0) {
1004
1005 vol->secFlg |= CIFSSEC_MAY_NTLM;
1006 } else if (strnicmp(value, "nontlm", 6) == 0) {
1007
1008 vol->secFlg |= CIFSSEC_MAY_NTLMV2;
1009#ifdef CONFIG_CIFS_WEAK_PW_HASH
1010 } else if (strnicmp(value, "lanman", 6) == 0) {
1011 vol->secFlg |= CIFSSEC_MAY_LANMAN;
1012#endif
1013 } else if (strnicmp(value, "none", 4) == 0) {
1014 vol->nullauth = 1;
1015 } else {
1016 cERROR(1, ("bad security option: %s", value));
1017 return 1;
1018 }
1019 } else if ((strnicmp(data, "unc", 3) == 0)
1020 || (strnicmp(data, "target", 6) == 0)
1021 || (strnicmp(data, "path", 4) == 0)) {
1022 if (!value || !*value) {
1023 printk(KERN_WARNING "CIFS: invalid path to "
1024 "network resource\n");
1025 return 1;
1026 }
1027 if ((temp_len = strnlen(value, 300)) < 300) {
1028 vol->UNC = kmalloc(temp_len+1, GFP_KERNEL);
1029 if (vol->UNC == NULL)
1030 return 1;
1031 strcpy(vol->UNC, value);
1032 if (strncmp(vol->UNC, "//", 2) == 0) {
1033 vol->UNC[0] = '\\';
1034 vol->UNC[1] = '\\';
1035 } else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
1036 printk(KERN_WARNING
1037 "CIFS: UNC Path does not begin "
1038 "with // or \\\\ \n");
1039 return 1;
1040 }
1041 } else {
1042 printk(KERN_WARNING "CIFS: UNC name too long\n");
1043 return 1;
1044 }
1045 } else if ((strnicmp(data, "domain", 3) == 0)
1046 || (strnicmp(data, "workgroup", 5) == 0)) {
1047 if (!value || !*value) {
1048 printk(KERN_WARNING "CIFS: invalid domain name\n");
1049 return 1;
1050 }
1051
1052
1053 if (strnlen(value, 256) < 256) {
1054 vol->domainname = value;
1055 cFYI(1, ("Domain name set"));
1056 } else {
1057 printk(KERN_WARNING "CIFS: domain name too "
1058 "long\n");
1059 return 1;
1060 }
1061 } else if (strnicmp(data, "prefixpath", 10) == 0) {
1062 if (!value || !*value) {
1063 printk(KERN_WARNING
1064 "CIFS: invalid path prefix\n");
1065 return 1;
1066 }
1067 if ((temp_len = strnlen(value, 1024)) < 1024) {
1068 if (value[0] != '/')
1069 temp_len++;
1070 vol->prepath = kmalloc(temp_len+1, GFP_KERNEL);
1071 if (vol->prepath == NULL)
1072 return 1;
1073 if (value[0] != '/') {
1074 vol->prepath[0] = '/';
1075 strcpy(vol->prepath+1, value);
1076 } else
1077 strcpy(vol->prepath, value);
1078 cFYI(1, ("prefix path %s", vol->prepath));
1079 } else {
1080 printk(KERN_WARNING "CIFS: prefix too long\n");
1081 return 1;
1082 }
1083 } else if (strnicmp(data, "iocharset", 9) == 0) {
1084 if (!value || !*value) {
1085 printk(KERN_WARNING "CIFS: invalid iocharset "
1086 "specified\n");
1087 return 1;
1088 }
1089 if (strnlen(value, 65) < 65) {
1090 if (strnicmp(value, "default", 7))
1091 vol->iocharset = value;
1092
1093
1094 cFYI(1, ("iocharset set to %s", value));
1095 } else {
1096 printk(KERN_WARNING "CIFS: iocharset name "
1097 "too long.\n");
1098 return 1;
1099 }
1100 } else if (!strnicmp(data, "uid", 3) && value && *value) {
1101 vol->linux_uid = simple_strtoul(value, &value, 0);
1102 uid_specified = true;
1103 } else if (!strnicmp(data, "forceuid", 8)) {
1104 override_uid = 1;
1105 } else if (!strnicmp(data, "noforceuid", 10)) {
1106 override_uid = 0;
1107 } else if (!strnicmp(data, "gid", 3) && value && *value) {
1108 vol->linux_gid = simple_strtoul(value, &value, 0);
1109 gid_specified = true;
1110 } else if (!strnicmp(data, "forcegid", 8)) {
1111 override_gid = 1;
1112 } else if (!strnicmp(data, "noforcegid", 10)) {
1113 override_gid = 0;
1114 } else if (strnicmp(data, "file_mode", 4) == 0) {
1115 if (value && *value) {
1116 vol->file_mode =
1117 simple_strtoul(value, &value, 0);
1118 }
1119 } else if (strnicmp(data, "dir_mode", 4) == 0) {
1120 if (value && *value) {
1121 vol->dir_mode =
1122 simple_strtoul(value, &value, 0);
1123 }
1124 } else if (strnicmp(data, "dirmode", 4) == 0) {
1125 if (value && *value) {
1126 vol->dir_mode =
1127 simple_strtoul(value, &value, 0);
1128 }
1129 } else if (strnicmp(data, "port", 4) == 0) {
1130 if (value && *value) {
1131 vol->port =
1132 simple_strtoul(value, &value, 0);
1133 }
1134 } else if (strnicmp(data, "rsize", 5) == 0) {
1135 if (value && *value) {
1136 vol->rsize =
1137 simple_strtoul(value, &value, 0);
1138 }
1139 } else if (strnicmp(data, "wsize", 5) == 0) {
1140 if (value && *value) {
1141 vol->wsize =
1142 simple_strtoul(value, &value, 0);
1143 }
1144 } else if (strnicmp(data, "sockopt", 5) == 0) {
1145 if (value && *value) {
1146 vol->sockopt =
1147 simple_strtoul(value, &value, 0);
1148 }
1149 } else if (strnicmp(data, "netbiosname", 4) == 0) {
1150 if (!value || !*value || (*value == ' ')) {
1151 cFYI(1, ("invalid (empty) netbiosname"));
1152 } else {
1153 memset(vol->source_rfc1001_name, 0x20, 15);
1154 for (i = 0; i < 15; i++) {
1155
1156
1157
1158
1159
1160 if (value[i] == 0)
1161 break;
1162 else
1163 vol->source_rfc1001_name[i] =
1164 value[i];
1165 }
1166
1167
1168 if ((i == 15) && (value[i] != 0))
1169 printk(KERN_WARNING "CIFS: netbiosname"
1170 " longer than 15 truncated.\n");
1171 }
1172 } else if (strnicmp(data, "servern", 7) == 0) {
1173
1174 if (!value || !*value || (*value == ' ')) {
1175 cFYI(1, ("empty server netbiosname specified"));
1176 } else {
1177
1178 memset(vol->target_rfc1001_name, 0x20, 16);
1179
1180 for (i = 0; i < 15; i++) {
1181
1182
1183
1184
1185
1186
1187 if (value[i] == 0)
1188 break;
1189 else
1190 vol->target_rfc1001_name[i] =
1191 value[i];
1192 }
1193
1194
1195 if ((i == 15) && (value[i] != 0))
1196 printk(KERN_WARNING "CIFS: server net"
1197 "biosname longer than 15 truncated.\n");
1198 }
1199 } else if (strnicmp(data, "credentials", 4) == 0) {
1200
1201 } else if (strnicmp(data, "version", 3) == 0) {
1202
1203 } else if (strnicmp(data, "guest", 5) == 0) {
1204
1205 } else if (strnicmp(data, "rw", 2) == 0) {
1206
1207 } else if (strnicmp(data, "ro", 2) == 0) {
1208
1209 } else if (strnicmp(data, "noblocksend", 11) == 0) {
1210 vol->noblocksnd = 1;
1211 } else if (strnicmp(data, "noautotune", 10) == 0) {
1212 vol->noautotune = 1;
1213 } else if ((strnicmp(data, "suid", 4) == 0) ||
1214 (strnicmp(data, "nosuid", 6) == 0) ||
1215 (strnicmp(data, "exec", 4) == 0) ||
1216 (strnicmp(data, "noexec", 6) == 0) ||
1217 (strnicmp(data, "nodev", 5) == 0) ||
1218 (strnicmp(data, "noauto", 6) == 0) ||
1219 (strnicmp(data, "dev", 3) == 0)) {
1220
1221
1222
1223
1224
1225
1226 continue;
1227 } else if (strnicmp(data, "hard", 4) == 0) {
1228 vol->retry = 1;
1229 } else if (strnicmp(data, "soft", 4) == 0) {
1230 vol->retry = 0;
1231 } else if (strnicmp(data, "perm", 4) == 0) {
1232 vol->noperm = 0;
1233 } else if (strnicmp(data, "noperm", 6) == 0) {
1234 vol->noperm = 1;
1235 } else if (strnicmp(data, "mapchars", 8) == 0) {
1236 vol->remap = 1;
1237 } else if (strnicmp(data, "nomapchars", 10) == 0) {
1238 vol->remap = 0;
1239 } else if (strnicmp(data, "sfu", 3) == 0) {
1240 vol->sfu_emul = 1;
1241 } else if (strnicmp(data, "nosfu", 5) == 0) {
1242 vol->sfu_emul = 0;
1243 } else if (strnicmp(data, "nodfs", 5) == 0) {
1244 vol->nodfs = 1;
1245 } else if (strnicmp(data, "posixpaths", 10) == 0) {
1246 vol->posix_paths = 1;
1247 } else if (strnicmp(data, "noposixpaths", 12) == 0) {
1248 vol->posix_paths = 0;
1249 } else if (strnicmp(data, "nounix", 6) == 0) {
1250 vol->no_linux_ext = 1;
1251 } else if (strnicmp(data, "nolinux", 7) == 0) {
1252 vol->no_linux_ext = 1;
1253 } else if ((strnicmp(data, "nocase", 6) == 0) ||
1254 (strnicmp(data, "ignorecase", 10) == 0)) {
1255 vol->nocase = 1;
1256 } else if (strnicmp(data, "brl", 3) == 0) {
1257 vol->nobrl = 0;
1258 } else if ((strnicmp(data, "nobrl", 5) == 0) ||
1259 (strnicmp(data, "nolock", 6) == 0)) {
1260 vol->nobrl = 1;
1261
1262
1263
1264 if (vol->file_mode ==
1265 (S_IALLUGO & ~(S_ISUID | S_IXGRP)))
1266 vol->file_mode = S_IALLUGO;
1267 } else if (strnicmp(data, "forcemandatorylock", 9) == 0) {
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277 vol->mand_lock = 1;
1278 } else if (strnicmp(data, "setuids", 7) == 0) {
1279 vol->setuids = 1;
1280 } else if (strnicmp(data, "nosetuids", 9) == 0) {
1281 vol->setuids = 0;
1282 } else if (strnicmp(data, "dynperm", 7) == 0) {
1283 vol->dynperm = true;
1284 } else if (strnicmp(data, "nodynperm", 9) == 0) {
1285 vol->dynperm = false;
1286 } else if (strnicmp(data, "nohard", 6) == 0) {
1287 vol->retry = 0;
1288 } else if (strnicmp(data, "nosoft", 6) == 0) {
1289 vol->retry = 1;
1290 } else if (strnicmp(data, "nointr", 6) == 0) {
1291 vol->intr = 0;
1292 } else if (strnicmp(data, "intr", 4) == 0) {
1293 vol->intr = 1;
1294 } else if (strnicmp(data, "nostrictsync", 12) == 0) {
1295 vol->nostrictsync = 1;
1296 } else if (strnicmp(data, "strictsync", 10) == 0) {
1297 vol->nostrictsync = 0;
1298 } else if (strnicmp(data, "serverino", 7) == 0) {
1299 vol->server_ino = 1;
1300 } else if (strnicmp(data, "noserverino", 9) == 0) {
1301 vol->server_ino = 0;
1302 } else if (strnicmp(data, "cifsacl", 7) == 0) {
1303 vol->cifs_acl = 1;
1304 } else if (strnicmp(data, "nocifsacl", 9) == 0) {
1305 vol->cifs_acl = 0;
1306 } else if (strnicmp(data, "acl", 3) == 0) {
1307 vol->no_psx_acl = 0;
1308 } else if (strnicmp(data, "noacl", 5) == 0) {
1309 vol->no_psx_acl = 1;
1310#ifdef CONFIG_CIFS_EXPERIMENTAL
1311 } else if (strnicmp(data, "locallease", 6) == 0) {
1312 vol->local_lease = 1;
1313#endif
1314 } else if (strnicmp(data, "sign", 4) == 0) {
1315 vol->secFlg |= CIFSSEC_MUST_SIGN;
1316 } else if (strnicmp(data, "seal", 4) == 0) {
1317
1318
1319
1320
1321 vol->seal = 1;
1322 } else if (strnicmp(data, "direct", 6) == 0) {
1323 vol->direct_io = 1;
1324 } else if (strnicmp(data, "forcedirectio", 13) == 0) {
1325 vol->direct_io = 1;
1326 } else if (strnicmp(data, "noac", 4) == 0) {
1327 printk(KERN_WARNING "CIFS: Mount option noac not "
1328 "supported. Instead set "
1329 "/proc/fs/cifs/LookupCacheEnabled to 0\n");
1330 } else
1331 printk(KERN_WARNING "CIFS: Unknown mount option %s\n",
1332 data);
1333 }
1334 if (vol->UNC == NULL) {
1335 if (devname == NULL) {
1336 printk(KERN_WARNING "CIFS: Missing UNC name for mount "
1337 "target\n");
1338 return 1;
1339 }
1340 if ((temp_len = strnlen(devname, 300)) < 300) {
1341 vol->UNC = kmalloc(temp_len+1, GFP_KERNEL);
1342 if (vol->UNC == NULL)
1343 return 1;
1344 strcpy(vol->UNC, devname);
1345 if (strncmp(vol->UNC, "//", 2) == 0) {
1346 vol->UNC[0] = '\\';
1347 vol->UNC[1] = '\\';
1348 } else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
1349 printk(KERN_WARNING "CIFS: UNC Path does not "
1350 "begin with // or \\\\ \n");
1351 return 1;
1352 }
1353 value = strpbrk(vol->UNC+2, "/\\");
1354 if (value)
1355 *value = '\\';
1356 } else {
1357 printk(KERN_WARNING "CIFS: UNC name too long\n");
1358 return 1;
1359 }
1360 }
1361 if (vol->UNCip == NULL)
1362 vol->UNCip = &vol->UNC[2];
1363
1364 if (uid_specified)
1365 vol->override_uid = override_uid;
1366 else if (override_uid == 1)
1367 printk(KERN_NOTICE "CIFS: ignoring forceuid mount option "
1368 "specified with no uid= option.\n");
1369
1370 if (gid_specified)
1371 vol->override_gid = override_gid;
1372 else if (override_gid == 1)
1373 printk(KERN_NOTICE "CIFS: ignoring forcegid mount option "
1374 "specified with no gid= option.\n");
1375
1376 return 0;
1377}
1378
1379static struct TCP_Server_Info *
1380cifs_find_tcp_session(struct sockaddr_storage *addr, unsigned short int port)
1381{
1382 struct list_head *tmp;
1383 struct TCP_Server_Info *server;
1384 struct sockaddr_in *addr4 = (struct sockaddr_in *) addr;
1385 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *) addr;
1386
1387 write_lock(&cifs_tcp_ses_lock);
1388 list_for_each(tmp, &cifs_tcp_ses_list) {
1389 server = list_entry(tmp, struct TCP_Server_Info,
1390 tcp_ses_list);
1391
1392
1393
1394
1395
1396
1397 if (server->tcpStatus == CifsNew)
1398 continue;
1399
1400 switch (addr->ss_family) {
1401 case AF_INET:
1402 if (addr4->sin_addr.s_addr ==
1403 server->addr.sockAddr.sin_addr.s_addr) {
1404 addr4->sin_port = htons(port);
1405
1406 if (addr4->sin_port) {
1407 if (addr4->sin_port !=
1408 server->addr.sockAddr.sin_port)
1409 continue;
1410 }
1411 break;
1412 } else
1413 continue;
1414
1415 case AF_INET6:
1416 if (ipv6_addr_equal(&addr6->sin6_addr,
1417 &server->addr.sockAddr6.sin6_addr) &&
1418 (addr6->sin6_scope_id ==
1419 server->addr.sockAddr6.sin6_scope_id)) {
1420 addr6->sin6_port = htons(port);
1421
1422 if (addr6->sin6_port) {
1423 if (addr6->sin6_port !=
1424 server->addr.sockAddr6.sin6_port)
1425 continue;
1426 }
1427 break;
1428 } else
1429 continue;
1430 }
1431
1432 ++server->srv_count;
1433 write_unlock(&cifs_tcp_ses_lock);
1434 cFYI(1, ("Existing tcp session with server found"));
1435 return server;
1436 }
1437 write_unlock(&cifs_tcp_ses_lock);
1438 return NULL;
1439}
1440
1441static void
1442cifs_put_tcp_session(struct TCP_Server_Info *server)
1443{
1444 struct task_struct *task;
1445
1446 write_lock(&cifs_tcp_ses_lock);
1447 if (--server->srv_count > 0) {
1448 write_unlock(&cifs_tcp_ses_lock);
1449 return;
1450 }
1451
1452 list_del_init(&server->tcp_ses_list);
1453 write_unlock(&cifs_tcp_ses_lock);
1454
1455 spin_lock(&GlobalMid_Lock);
1456 server->tcpStatus = CifsExiting;
1457 spin_unlock(&GlobalMid_Lock);
1458
1459 task = xchg(&server->tsk, NULL);
1460 if (task)
1461 force_sig(SIGKILL, task);
1462}
1463
1464static struct TCP_Server_Info *
1465cifs_get_tcp_session(struct smb_vol *volume_info)
1466{
1467 struct TCP_Server_Info *tcp_ses = NULL;
1468 struct sockaddr_storage addr;
1469 struct sockaddr_in *sin_server = (struct sockaddr_in *) &addr;
1470 struct sockaddr_in6 *sin_server6 = (struct sockaddr_in6 *) &addr;
1471 int rc;
1472
1473 memset(&addr, 0, sizeof(struct sockaddr_storage));
1474
1475 cFYI(1, ("UNC: %s ip: %s", volume_info->UNC, volume_info->UNCip));
1476
1477 if (volume_info->UNCip && volume_info->UNC) {
1478 rc = cifs_convert_address(volume_info->UNCip, &addr);
1479 if (!rc) {
1480
1481 rc = -EINVAL;
1482 goto out_err;
1483 }
1484 } else if (volume_info->UNCip) {
1485
1486
1487 cERROR(1, ("Connecting to DFS root not implemented yet"));
1488 rc = -EINVAL;
1489 goto out_err;
1490 } else {
1491 cERROR(1,
1492 ("CIFS mount error: No UNC path (e.g. -o "
1493 "unc=//192.168.1.100/public) specified"));
1494 rc = -EINVAL;
1495 goto out_err;
1496 }
1497
1498
1499 tcp_ses = cifs_find_tcp_session(&addr, volume_info->port);
1500 if (tcp_ses)
1501 return tcp_ses;
1502
1503 tcp_ses = kzalloc(sizeof(struct TCP_Server_Info), GFP_KERNEL);
1504 if (!tcp_ses) {
1505 rc = -ENOMEM;
1506 goto out_err;
1507 }
1508
1509 tcp_ses->hostname = extract_hostname(volume_info->UNC);
1510 if (IS_ERR(tcp_ses->hostname)) {
1511 rc = PTR_ERR(tcp_ses->hostname);
1512 goto out_err;
1513 }
1514
1515 tcp_ses->noblocksnd = volume_info->noblocksnd;
1516 tcp_ses->noautotune = volume_info->noautotune;
1517 atomic_set(&tcp_ses->inFlight, 0);
1518 init_waitqueue_head(&tcp_ses->response_q);
1519 init_waitqueue_head(&tcp_ses->request_q);
1520 INIT_LIST_HEAD(&tcp_ses->pending_mid_q);
1521 mutex_init(&tcp_ses->srv_mutex);
1522 memcpy(tcp_ses->workstation_RFC1001_name,
1523 volume_info->source_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL);
1524 memcpy(tcp_ses->server_RFC1001_name,
1525 volume_info->target_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL);
1526 tcp_ses->sequence_number = 0;
1527 INIT_LIST_HEAD(&tcp_ses->tcp_ses_list);
1528 INIT_LIST_HEAD(&tcp_ses->smb_ses_list);
1529
1530
1531
1532
1533
1534
1535 tcp_ses->tcpStatus = CifsNew;
1536 ++tcp_ses->srv_count;
1537
1538 if (addr.ss_family == AF_INET6) {
1539 cFYI(1, ("attempting ipv6 connect"));
1540
1541
1542 sin_server6->sin6_port = htons(volume_info->port);
1543 memcpy(&tcp_ses->addr.sockAddr6, sin_server6,
1544 sizeof(struct sockaddr_in6));
1545 rc = ipv6_connect(tcp_ses);
1546 } else {
1547 sin_server->sin_port = htons(volume_info->port);
1548 memcpy(&tcp_ses->addr.sockAddr, sin_server,
1549 sizeof(struct sockaddr_in));
1550 rc = ipv4_connect(tcp_ses);
1551 }
1552 if (rc < 0) {
1553 cERROR(1, ("Error connecting to socket. Aborting operation"));
1554 goto out_err;
1555 }
1556
1557
1558
1559
1560
1561 __module_get(THIS_MODULE);
1562 tcp_ses->tsk = kthread_run((void *)(void *)cifs_demultiplex_thread,
1563 tcp_ses, "cifsd");
1564 if (IS_ERR(tcp_ses->tsk)) {
1565 rc = PTR_ERR(tcp_ses->tsk);
1566 cERROR(1, ("error %d create cifsd thread", rc));
1567 module_put(THIS_MODULE);
1568 goto out_err;
1569 }
1570
1571
1572 write_lock(&cifs_tcp_ses_lock);
1573 list_add(&tcp_ses->tcp_ses_list, &cifs_tcp_ses_list);
1574 write_unlock(&cifs_tcp_ses_lock);
1575
1576 return tcp_ses;
1577
1578out_err:
1579 if (tcp_ses) {
1580 if (!IS_ERR(tcp_ses->hostname))
1581 kfree(tcp_ses->hostname);
1582 if (tcp_ses->ssocket)
1583 sock_release(tcp_ses->ssocket);
1584 kfree(tcp_ses);
1585 }
1586 return ERR_PTR(rc);
1587}
1588
1589static struct cifsSesInfo *
1590cifs_find_smb_ses(struct TCP_Server_Info *server, char *username)
1591{
1592 struct list_head *tmp;
1593 struct cifsSesInfo *ses;
1594
1595 write_lock(&cifs_tcp_ses_lock);
1596 list_for_each(tmp, &server->smb_ses_list) {
1597 ses = list_entry(tmp, struct cifsSesInfo, smb_ses_list);
1598 if (strncmp(ses->userName, username, MAX_USERNAME_SIZE))
1599 continue;
1600
1601 ++ses->ses_count;
1602 write_unlock(&cifs_tcp_ses_lock);
1603 return ses;
1604 }
1605 write_unlock(&cifs_tcp_ses_lock);
1606 return NULL;
1607}
1608
1609static void
1610cifs_put_smb_ses(struct cifsSesInfo *ses)
1611{
1612 int xid;
1613 struct TCP_Server_Info *server = ses->server;
1614
1615 write_lock(&cifs_tcp_ses_lock);
1616 if (--ses->ses_count > 0) {
1617 write_unlock(&cifs_tcp_ses_lock);
1618 return;
1619 }
1620
1621 list_del_init(&ses->smb_ses_list);
1622 write_unlock(&cifs_tcp_ses_lock);
1623
1624 if (ses->status == CifsGood) {
1625 xid = GetXid();
1626 CIFSSMBLogoff(xid, ses);
1627 _FreeXid(xid);
1628 }
1629 sesInfoFree(ses);
1630 cifs_put_tcp_session(server);
1631}
1632
1633static struct cifsTconInfo *
1634cifs_find_tcon(struct cifsSesInfo *ses, const char *unc)
1635{
1636 struct list_head *tmp;
1637 struct cifsTconInfo *tcon;
1638
1639 write_lock(&cifs_tcp_ses_lock);
1640 list_for_each(tmp, &ses->tcon_list) {
1641 tcon = list_entry(tmp, struct cifsTconInfo, tcon_list);
1642 if (tcon->tidStatus == CifsExiting)
1643 continue;
1644 if (strncmp(tcon->treeName, unc, MAX_TREE_SIZE))
1645 continue;
1646
1647 ++tcon->tc_count;
1648 write_unlock(&cifs_tcp_ses_lock);
1649 return tcon;
1650 }
1651 write_unlock(&cifs_tcp_ses_lock);
1652 return NULL;
1653}
1654
1655static void
1656cifs_put_tcon(struct cifsTconInfo *tcon)
1657{
1658 int xid;
1659 struct cifsSesInfo *ses = tcon->ses;
1660
1661 write_lock(&cifs_tcp_ses_lock);
1662 if (--tcon->tc_count > 0) {
1663 write_unlock(&cifs_tcp_ses_lock);
1664 return;
1665 }
1666
1667 list_del_init(&tcon->tcon_list);
1668 write_unlock(&cifs_tcp_ses_lock);
1669
1670 xid = GetXid();
1671 CIFSSMBTDis(xid, tcon);
1672 _FreeXid(xid);
1673
1674 tconInfoFree(tcon);
1675 cifs_put_smb_ses(ses);
1676}
1677
1678int
1679get_dfs_path(int xid, struct cifsSesInfo *pSesInfo, const char *old_path,
1680 const struct nls_table *nls_codepage, unsigned int *pnum_referrals,
1681 struct dfs_info3_param **preferrals, int remap)
1682{
1683 char *temp_unc;
1684 int rc = 0;
1685
1686 *pnum_referrals = 0;
1687 *preferrals = NULL;
1688
1689 if (pSesInfo->ipc_tid == 0) {
1690 temp_unc = kmalloc(2 +
1691 strnlen(pSesInfo->serverName,
1692 SERVER_NAME_LEN_WITH_NULL * 2)
1693 + 1 + 4 + 2,
1694 GFP_KERNEL);
1695 if (temp_unc == NULL)
1696 return -ENOMEM;
1697 temp_unc[0] = '\\';
1698 temp_unc[1] = '\\';
1699 strcpy(temp_unc + 2, pSesInfo->serverName);
1700 strcpy(temp_unc + 2 + strlen(pSesInfo->serverName), "\\IPC$");
1701 rc = CIFSTCon(xid, pSesInfo, temp_unc, NULL, nls_codepage);
1702 cFYI(1,
1703 ("CIFS Tcon rc = %d ipc_tid = %d", rc, pSesInfo->ipc_tid));
1704 kfree(temp_unc);
1705 }
1706 if (rc == 0)
1707 rc = CIFSGetDFSRefer(xid, pSesInfo, old_path, preferrals,
1708 pnum_referrals, nls_codepage, remap);
1709
1710
1711
1712 return rc;
1713}
1714
1715#ifdef CONFIG_DEBUG_LOCK_ALLOC
1716static struct lock_class_key cifs_key[2];
1717static struct lock_class_key cifs_slock_key[2];
1718
1719static inline void
1720cifs_reclassify_socket4(struct socket *sock)
1721{
1722 struct sock *sk = sock->sk;
1723 BUG_ON(sock_owned_by_user(sk));
1724 sock_lock_init_class_and_name(sk, "slock-AF_INET-CIFS",
1725 &cifs_slock_key[0], "sk_lock-AF_INET-CIFS", &cifs_key[0]);
1726}
1727
1728static inline void
1729cifs_reclassify_socket6(struct socket *sock)
1730{
1731 struct sock *sk = sock->sk;
1732 BUG_ON(sock_owned_by_user(sk));
1733 sock_lock_init_class_and_name(sk, "slock-AF_INET6-CIFS",
1734 &cifs_slock_key[1], "sk_lock-AF_INET6-CIFS", &cifs_key[1]);
1735}
1736#else
1737static inline void
1738cifs_reclassify_socket4(struct socket *sock)
1739{
1740}
1741
1742static inline void
1743cifs_reclassify_socket6(struct socket *sock)
1744{
1745}
1746#endif
1747
1748
1749static void rfc1002mangle(char *target, char *source, unsigned int length)
1750{
1751 unsigned int i, j;
1752
1753 for (i = 0, j = 0; i < (length); i++) {
1754
1755 target[j] = 'A' + (0x0F & (source[i] >> 4));
1756 target[j+1] = 'A' + (0x0F & source[i]);
1757 j += 2;
1758 }
1759
1760}
1761
1762
1763static int
1764ipv4_connect(struct TCP_Server_Info *server)
1765{
1766 int rc = 0;
1767 bool connected = false;
1768 __be16 orig_port = 0;
1769 struct socket *socket = server->ssocket;
1770
1771 if (socket == NULL) {
1772 rc = sock_create_kern(PF_INET, SOCK_STREAM,
1773 IPPROTO_TCP, &socket);
1774 if (rc < 0) {
1775 cERROR(1, ("Error %d creating socket", rc));
1776 return rc;
1777 }
1778
1779
1780 cFYI(1, ("Socket created"));
1781 server->ssocket = socket;
1782 socket->sk->sk_allocation = GFP_NOFS;
1783 cifs_reclassify_socket4(socket);
1784 }
1785
1786
1787 if (server->addr.sockAddr.sin_port) {
1788 rc = socket->ops->connect(socket, (struct sockaddr *)
1789 &server->addr.sockAddr,
1790 sizeof(struct sockaddr_in), 0);
1791 if (rc >= 0)
1792 connected = true;
1793 }
1794
1795 if (!connected) {
1796
1797
1798 orig_port = server->addr.sockAddr.sin_port;
1799
1800
1801 if (server->addr.sockAddr.sin_port != htons(CIFS_PORT)) {
1802 server->addr.sockAddr.sin_port = htons(CIFS_PORT);
1803 rc = socket->ops->connect(socket,
1804 (struct sockaddr *)
1805 &server->addr.sockAddr,
1806 sizeof(struct sockaddr_in), 0);
1807 if (rc >= 0)
1808 connected = true;
1809 }
1810 }
1811 if (!connected) {
1812 server->addr.sockAddr.sin_port = htons(RFC1001_PORT);
1813 rc = socket->ops->connect(socket, (struct sockaddr *)
1814 &server->addr.sockAddr,
1815 sizeof(struct sockaddr_in), 0);
1816 if (rc >= 0)
1817 connected = true;
1818 }
1819
1820
1821
1822 if (!connected) {
1823 if (orig_port)
1824 server->addr.sockAddr.sin_port = orig_port;
1825 cFYI(1, ("Error %d connecting to server via ipv4", rc));
1826 sock_release(socket);
1827 server->ssocket = NULL;
1828 return rc;
1829 }
1830
1831
1832
1833
1834
1835
1836
1837 socket->sk->sk_rcvtimeo = 7 * HZ;
1838 socket->sk->sk_sndtimeo = 5 * HZ;
1839
1840
1841 if (server->noautotune) {
1842 if (socket->sk->sk_sndbuf < (200 * 1024))
1843 socket->sk->sk_sndbuf = 200 * 1024;
1844 if (socket->sk->sk_rcvbuf < (140 * 1024))
1845 socket->sk->sk_rcvbuf = 140 * 1024;
1846 }
1847
1848 cFYI(1, ("sndbuf %d rcvbuf %d rcvtimeo 0x%lx",
1849 socket->sk->sk_sndbuf,
1850 socket->sk->sk_rcvbuf, socket->sk->sk_rcvtimeo));
1851
1852
1853 if (server->addr.sockAddr.sin_port == htons(RFC1001_PORT)) {
1854
1855
1856
1857 struct rfc1002_session_packet *ses_init_buf;
1858 struct smb_hdr *smb_buf;
1859 ses_init_buf = kzalloc(sizeof(struct rfc1002_session_packet),
1860 GFP_KERNEL);
1861 if (ses_init_buf) {
1862 ses_init_buf->trailer.session_req.called_len = 32;
1863 if (server->server_RFC1001_name &&
1864 server->server_RFC1001_name[0] != 0)
1865 rfc1002mangle(ses_init_buf->trailer.
1866 session_req.called_name,
1867 server->server_RFC1001_name,
1868 RFC1001_NAME_LEN_WITH_NULL);
1869 else
1870 rfc1002mangle(ses_init_buf->trailer.
1871 session_req.called_name,
1872 DEFAULT_CIFS_CALLED_NAME,
1873 RFC1001_NAME_LEN_WITH_NULL);
1874
1875 ses_init_buf->trailer.session_req.calling_len = 32;
1876
1877
1878
1879 if (server->workstation_RFC1001_name &&
1880 server->workstation_RFC1001_name[0] != 0)
1881 rfc1002mangle(ses_init_buf->trailer.
1882 session_req.calling_name,
1883 server->workstation_RFC1001_name,
1884 RFC1001_NAME_LEN_WITH_NULL);
1885 else
1886 rfc1002mangle(ses_init_buf->trailer.
1887 session_req.calling_name,
1888 "LINUX_CIFS_CLNT",
1889 RFC1001_NAME_LEN_WITH_NULL);
1890
1891 ses_init_buf->trailer.session_req.scope1 = 0;
1892 ses_init_buf->trailer.session_req.scope2 = 0;
1893 smb_buf = (struct smb_hdr *)ses_init_buf;
1894
1895 smb_buf->smb_buf_length = 0x81000044;
1896 rc = smb_send(server, smb_buf, 0x44);
1897 kfree(ses_init_buf);
1898 msleep(1);
1899
1900
1901
1902
1903
1904
1905
1906 }
1907
1908
1909
1910 }
1911
1912 return rc;
1913}
1914
1915static int
1916ipv6_connect(struct TCP_Server_Info *server)
1917{
1918 int rc = 0;
1919 bool connected = false;
1920 __be16 orig_port = 0;
1921 struct socket *socket = server->ssocket;
1922
1923 if (socket == NULL) {
1924 rc = sock_create_kern(PF_INET6, SOCK_STREAM,
1925 IPPROTO_TCP, &socket);
1926 if (rc < 0) {
1927 cERROR(1, ("Error %d creating ipv6 socket", rc));
1928 socket = NULL;
1929 return rc;
1930 }
1931
1932
1933 cFYI(1, ("ipv6 Socket created"));
1934 server->ssocket = socket;
1935 socket->sk->sk_allocation = GFP_NOFS;
1936 cifs_reclassify_socket6(socket);
1937 }
1938
1939
1940 if (server->addr.sockAddr6.sin6_port) {
1941 rc = socket->ops->connect(socket,
1942 (struct sockaddr *) &server->addr.sockAddr6,
1943 sizeof(struct sockaddr_in6), 0);
1944 if (rc >= 0)
1945 connected = true;
1946 }
1947
1948 if (!connected) {
1949
1950
1951
1952 orig_port = server->addr.sockAddr6.sin6_port;
1953
1954 if (server->addr.sockAddr6.sin6_port != htons(CIFS_PORT)) {
1955 server->addr.sockAddr6.sin6_port = htons(CIFS_PORT);
1956 rc = socket->ops->connect(socket, (struct sockaddr *)
1957 &server->addr.sockAddr6,
1958 sizeof(struct sockaddr_in6), 0);
1959 if (rc >= 0)
1960 connected = true;
1961 }
1962 }
1963 if (!connected) {
1964 server->addr.sockAddr6.sin6_port = htons(RFC1001_PORT);
1965 rc = socket->ops->connect(socket, (struct sockaddr *)
1966 &server->addr.sockAddr6,
1967 sizeof(struct sockaddr_in6), 0);
1968 if (rc >= 0)
1969 connected = true;
1970 }
1971
1972
1973
1974 if (!connected) {
1975 if (orig_port)
1976 server->addr.sockAddr6.sin6_port = orig_port;
1977 cFYI(1, ("Error %d connecting to server via ipv6", rc));
1978 sock_release(socket);
1979 server->ssocket = NULL;
1980 return rc;
1981 }
1982
1983
1984
1985
1986
1987
1988 socket->sk->sk_rcvtimeo = 7 * HZ;
1989 socket->sk->sk_sndtimeo = 5 * HZ;
1990 server->ssocket = socket;
1991
1992 return rc;
1993}
1994
1995void reset_cifs_unix_caps(int xid, struct cifsTconInfo *tcon,
1996 struct super_block *sb, struct smb_vol *vol_info)
1997{
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007 __u64 saved_cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
2008
2009 if (vol_info && vol_info->no_linux_ext) {
2010 tcon->fsUnixInfo.Capability = 0;
2011 tcon->unix_ext = 0;
2012 cFYI(1, ("Linux protocol extensions disabled"));
2013 return;
2014 } else if (vol_info)
2015 tcon->unix_ext = 1;
2016
2017 if (tcon->unix_ext == 0) {
2018 cFYI(1, ("Unix extensions disabled so not set on reconnect"));
2019 return;
2020 }
2021
2022 if (!CIFSSMBQFSUnixInfo(xid, tcon)) {
2023 __u64 cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
2024
2025
2026
2027 if (vol_info == NULL) {
2028
2029
2030 if ((saved_cap & CIFS_UNIX_POSIX_ACL_CAP) == 0)
2031 cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
2032 if ((saved_cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) {
2033 if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
2034 cERROR(1, ("POSIXPATH support change"));
2035 cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
2036 } else if ((cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) {
2037 cERROR(1, ("possible reconnect error"));
2038 cERROR(1,
2039 ("server disabled POSIX path support"));
2040 }
2041 }
2042
2043 cap &= CIFS_UNIX_CAP_MASK;
2044 if (vol_info && vol_info->no_psx_acl)
2045 cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
2046 else if (CIFS_UNIX_POSIX_ACL_CAP & cap) {
2047 cFYI(1, ("negotiated posix acl support"));
2048 if (sb)
2049 sb->s_flags |= MS_POSIXACL;
2050 }
2051
2052 if (vol_info && vol_info->posix_paths == 0)
2053 cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
2054 else if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
2055 cFYI(1, ("negotiate posix pathnames"));
2056 if (sb)
2057 CIFS_SB(sb)->mnt_cifs_flags |=
2058 CIFS_MOUNT_POSIX_PATHS;
2059 }
2060
2061
2062
2063
2064 if (sb && (CIFS_SB(sb)->prepathlen > 0))
2065 CIFS_SB(sb)->prepath[0] = CIFS_DIR_SEP(CIFS_SB(sb));
2066
2067 if (sb && (CIFS_SB(sb)->rsize > 127 * 1024)) {
2068 if ((cap & CIFS_UNIX_LARGE_READ_CAP) == 0) {
2069 CIFS_SB(sb)->rsize = 127 * 1024;
2070 cFYI(DBG2,
2071 ("larger reads not supported by srv"));
2072 }
2073 }
2074
2075
2076 cFYI(1, ("Negotiate caps 0x%x", (int)cap));
2077#ifdef CONFIG_CIFS_DEBUG2
2078 if (cap & CIFS_UNIX_FCNTL_CAP)
2079 cFYI(1, ("FCNTL cap"));
2080 if (cap & CIFS_UNIX_EXTATTR_CAP)
2081 cFYI(1, ("EXTATTR cap"));
2082 if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
2083 cFYI(1, ("POSIX path cap"));
2084 if (cap & CIFS_UNIX_XATTR_CAP)
2085 cFYI(1, ("XATTR cap"));
2086 if (cap & CIFS_UNIX_POSIX_ACL_CAP)
2087 cFYI(1, ("POSIX ACL cap"));
2088 if (cap & CIFS_UNIX_LARGE_READ_CAP)
2089 cFYI(1, ("very large read cap"));
2090 if (cap & CIFS_UNIX_LARGE_WRITE_CAP)
2091 cFYI(1, ("very large write cap"));
2092#endif
2093 if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) {
2094 if (vol_info == NULL) {
2095 cFYI(1, ("resetting capabilities failed"));
2096 } else
2097 cERROR(1, ("Negotiating Unix capabilities "
2098 "with the server failed. Consider "
2099 "mounting with the Unix Extensions\n"
2100 "disabled, if problems are found, "
2101 "by specifying the nounix mount "
2102 "option."));
2103
2104 }
2105 }
2106}
2107
2108static void
2109convert_delimiter(char *path, char delim)
2110{
2111 int i;
2112 char old_delim;
2113
2114 if (path == NULL)
2115 return;
2116
2117 if (delim == '/')
2118 old_delim = '\\';
2119 else
2120 old_delim = '/';
2121
2122 for (i = 0; path[i] != '\0'; i++) {
2123 if (path[i] == old_delim)
2124 path[i] = delim;
2125 }
2126}
2127
2128static void setup_cifs_sb(struct smb_vol *pvolume_info,
2129 struct cifs_sb_info *cifs_sb)
2130{
2131 if (pvolume_info->rsize > CIFSMaxBufSize) {
2132 cERROR(1, ("rsize %d too large, using MaxBufSize",
2133 pvolume_info->rsize));
2134 cifs_sb->rsize = CIFSMaxBufSize;
2135 } else if ((pvolume_info->rsize) &&
2136 (pvolume_info->rsize <= CIFSMaxBufSize))
2137 cifs_sb->rsize = pvolume_info->rsize;
2138 else
2139 cifs_sb->rsize = CIFSMaxBufSize;
2140
2141 if (pvolume_info->wsize > PAGEVEC_SIZE * PAGE_CACHE_SIZE) {
2142 cERROR(1, ("wsize %d too large, using 4096 instead",
2143 pvolume_info->wsize));
2144 cifs_sb->wsize = 4096;
2145 } else if (pvolume_info->wsize)
2146 cifs_sb->wsize = pvolume_info->wsize;
2147 else
2148 cifs_sb->wsize = min_t(const int,
2149 PAGEVEC_SIZE * PAGE_CACHE_SIZE,
2150 127*1024);
2151
2152
2153
2154
2155
2156
2157
2158 if (cifs_sb->rsize < 2048) {
2159 cifs_sb->rsize = 2048;
2160
2161 cFYI(1, ("readsize set to minimum: 2048"));
2162 }
2163
2164 cifs_sb->prepath = pvolume_info->prepath;
2165 if (cifs_sb->prepath) {
2166 cifs_sb->prepathlen = strlen(cifs_sb->prepath);
2167
2168
2169
2170
2171
2172 pvolume_info->prepath = NULL;
2173 } else
2174 cifs_sb->prepathlen = 0;
2175 cifs_sb->mnt_uid = pvolume_info->linux_uid;
2176 cifs_sb->mnt_gid = pvolume_info->linux_gid;
2177 cifs_sb->mnt_file_mode = pvolume_info->file_mode;
2178 cifs_sb->mnt_dir_mode = pvolume_info->dir_mode;
2179 cFYI(1, ("file mode: 0x%x dir mode: 0x%x",
2180 cifs_sb->mnt_file_mode, cifs_sb->mnt_dir_mode));
2181
2182 if (pvolume_info->noperm)
2183 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
2184 if (pvolume_info->setuids)
2185 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
2186 if (pvolume_info->server_ino)
2187 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
2188 if (pvolume_info->remap)
2189 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
2190 if (pvolume_info->no_xattr)
2191 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
2192 if (pvolume_info->sfu_emul)
2193 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL;
2194 if (pvolume_info->nobrl)
2195 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL;
2196 if (pvolume_info->nostrictsync)
2197 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOSSYNC;
2198 if (pvolume_info->mand_lock)
2199 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOPOSIXBRL;
2200 if (pvolume_info->cifs_acl)
2201 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL;
2202 if (pvolume_info->override_uid)
2203 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_UID;
2204 if (pvolume_info->override_gid)
2205 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_GID;
2206 if (pvolume_info->dynperm)
2207 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DYNPERM;
2208 if (pvolume_info->direct_io) {
2209 cFYI(1, ("mounting share using direct i/o"));
2210 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
2211 }
2212
2213 if ((pvolume_info->cifs_acl) && (pvolume_info->dynperm))
2214 cERROR(1, ("mount option dynperm ignored if cifsacl "
2215 "mount option supported"));
2216}
2217
2218static int
2219is_path_accessible(int xid, struct cifsTconInfo *tcon,
2220 struct cifs_sb_info *cifs_sb, const char *full_path)
2221{
2222 int rc;
2223 FILE_ALL_INFO *pfile_info;
2224
2225 pfile_info = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
2226 if (pfile_info == NULL)
2227 return -ENOMEM;
2228
2229 rc = CIFSSMBQPathInfo(xid, tcon, full_path, pfile_info,
2230 0 , cifs_sb->local_nls,
2231 cifs_sb->mnt_cifs_flags &
2232 CIFS_MOUNT_MAP_SPECIAL_CHR);
2233 kfree(pfile_info);
2234 return rc;
2235}
2236
2237static void
2238cleanup_volume_info(struct smb_vol **pvolume_info)
2239{
2240 struct smb_vol *volume_info;
2241
2242 if (!pvolume_info && !*pvolume_info)
2243 return;
2244
2245 volume_info = *pvolume_info;
2246 kzfree(volume_info->password);
2247 kfree(volume_info->UNC);
2248 kfree(volume_info->prepath);
2249 kfree(volume_info);
2250 *pvolume_info = NULL;
2251 return;
2252}
2253
2254#ifdef CONFIG_CIFS_DFS_UPCALL
2255
2256
2257static char *
2258build_unc_path_to_root(const struct smb_vol *volume_info,
2259 const struct cifs_sb_info *cifs_sb)
2260{
2261 char *full_path;
2262
2263 int unc_len = strnlen(volume_info->UNC, MAX_TREE_SIZE + 1);
2264 full_path = kmalloc(unc_len + cifs_sb->prepathlen + 1, GFP_KERNEL);
2265 if (full_path == NULL)
2266 return ERR_PTR(-ENOMEM);
2267
2268 strncpy(full_path, volume_info->UNC, unc_len);
2269 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) {
2270 int i;
2271 for (i = 0; i < unc_len; i++) {
2272 if (full_path[i] == '\\')
2273 full_path[i] = '/';
2274 }
2275 }
2276
2277 if (cifs_sb->prepathlen)
2278 strncpy(full_path + unc_len, cifs_sb->prepath,
2279 cifs_sb->prepathlen);
2280
2281 full_path[unc_len + cifs_sb->prepathlen] = 0;
2282 return full_path;
2283}
2284#endif
2285
2286int
2287cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
2288 char *mount_data_global, const char *devname)
2289{
2290 int rc = 0;
2291 int xid;
2292 struct smb_vol *volume_info;
2293 struct cifsSesInfo *pSesInfo = NULL;
2294 struct cifsTconInfo *tcon = NULL;
2295 struct TCP_Server_Info *srvTcp = NULL;
2296 char *full_path;
2297 char *mount_data = mount_data_global;
2298#ifdef CONFIG_CIFS_DFS_UPCALL
2299 struct dfs_info3_param *referrals = NULL;
2300 unsigned int num_referrals = 0;
2301 int referral_walks_count = 0;
2302try_mount_again:
2303#endif
2304 full_path = NULL;
2305
2306 xid = GetXid();
2307
2308 volume_info = kzalloc(sizeof(struct smb_vol), GFP_KERNEL);
2309 if (!volume_info) {
2310 rc = -ENOMEM;
2311 goto out;
2312 }
2313
2314 if (cifs_parse_mount_options(mount_data, devname, volume_info)) {
2315 rc = -EINVAL;
2316 goto out;
2317 }
2318
2319 if (volume_info->nullauth) {
2320 cFYI(1, ("null user"));
2321 volume_info->username = "";
2322 } else if (volume_info->username) {
2323
2324 cFYI(1, ("Username: %s", volume_info->username));
2325 } else {
2326 cifserror("No username specified");
2327
2328
2329 rc = -EINVAL;
2330 goto out;
2331 }
2332
2333
2334
2335 if (volume_info->iocharset == NULL) {
2336 cifs_sb->local_nls = load_nls_default();
2337
2338 } else {
2339 cifs_sb->local_nls = load_nls(volume_info->iocharset);
2340 if (cifs_sb->local_nls == NULL) {
2341 cERROR(1, ("CIFS mount error: iocharset %s not found",
2342 volume_info->iocharset));
2343 rc = -ELIBACC;
2344 goto out;
2345 }
2346 }
2347
2348
2349 srvTcp = cifs_get_tcp_session(volume_info);
2350 if (IS_ERR(srvTcp)) {
2351 rc = PTR_ERR(srvTcp);
2352 goto out;
2353 }
2354
2355 pSesInfo = cifs_find_smb_ses(srvTcp, volume_info->username);
2356 if (pSesInfo) {
2357 cFYI(1, ("Existing smb sess found (status=%d)",
2358 pSesInfo->status));
2359
2360
2361
2362
2363 cifs_put_tcp_session(srvTcp);
2364
2365 down(&pSesInfo->sesSem);
2366 if (pSesInfo->need_reconnect) {
2367 cFYI(1, ("Session needs reconnect"));
2368 rc = cifs_setup_session(xid, pSesInfo,
2369 cifs_sb->local_nls);
2370 }
2371 up(&pSesInfo->sesSem);
2372 } else if (!rc) {
2373 cFYI(1, ("Existing smb sess not found"));
2374 pSesInfo = sesInfoAlloc();
2375 if (pSesInfo == NULL) {
2376 rc = -ENOMEM;
2377 goto mount_fail_check;
2378 }
2379
2380
2381 pSesInfo->server = srvTcp;
2382 if (srvTcp->addr.sockAddr6.sin6_family == AF_INET6)
2383 sprintf(pSesInfo->serverName, "%pI6",
2384 &srvTcp->addr.sockAddr6.sin6_addr);
2385 else
2386 sprintf(pSesInfo->serverName, "%pI4",
2387 &srvTcp->addr.sockAddr.sin_addr.s_addr);
2388
2389 write_lock(&cifs_tcp_ses_lock);
2390 list_add(&pSesInfo->smb_ses_list, &srvTcp->smb_ses_list);
2391 write_unlock(&cifs_tcp_ses_lock);
2392
2393
2394 if (volume_info->password) {
2395 pSesInfo->password = kstrdup(volume_info->password,
2396 GFP_KERNEL);
2397 if (!pSesInfo->password) {
2398 rc = -ENOMEM;
2399 goto mount_fail_check;
2400 }
2401 }
2402 if (volume_info->username)
2403 strncpy(pSesInfo->userName, volume_info->username,
2404 MAX_USERNAME_SIZE);
2405 if (volume_info->domainname) {
2406 int len = strlen(volume_info->domainname);
2407 pSesInfo->domainName = kmalloc(len + 1, GFP_KERNEL);
2408 if (pSesInfo->domainName)
2409 strcpy(pSesInfo->domainName,
2410 volume_info->domainname);
2411 }
2412 pSesInfo->linux_uid = volume_info->linux_uid;
2413 pSesInfo->overrideSecFlg = volume_info->secFlg;
2414 down(&pSesInfo->sesSem);
2415
2416
2417 rc = cifs_setup_session(xid, pSesInfo,
2418 cifs_sb->local_nls);
2419 up(&pSesInfo->sesSem);
2420 }
2421
2422
2423 if (!rc) {
2424 setup_cifs_sb(volume_info, cifs_sb);
2425
2426 tcon = cifs_find_tcon(pSesInfo, volume_info->UNC);
2427 if (tcon) {
2428 cFYI(1, ("Found match on UNC path"));
2429
2430 cifs_put_smb_ses(pSesInfo);
2431 if (tcon->seal != volume_info->seal)
2432 cERROR(1, ("transport encryption setting "
2433 "conflicts with existing tid"));
2434 } else {
2435 tcon = tconInfoAlloc();
2436 if (tcon == NULL) {
2437 rc = -ENOMEM;
2438 goto mount_fail_check;
2439 }
2440
2441 tcon->ses = pSesInfo;
2442 if (volume_info->password) {
2443 tcon->password = kstrdup(volume_info->password,
2444 GFP_KERNEL);
2445 if (!tcon->password) {
2446 rc = -ENOMEM;
2447 goto mount_fail_check;
2448 }
2449 }
2450
2451 if ((strchr(volume_info->UNC + 3, '\\') == NULL)
2452 && (strchr(volume_info->UNC + 3, '/') == NULL)) {
2453 cERROR(1, ("Missing share name"));
2454 rc = -ENODEV;
2455 goto mount_fail_check;
2456 } else {
2457
2458
2459
2460 rc = CIFSTCon(xid, pSesInfo, volume_info->UNC,
2461 tcon, cifs_sb->local_nls);
2462 cFYI(1, ("CIFS Tcon rc = %d", rc));
2463 if (volume_info->nodfs) {
2464 tcon->Flags &= ~SMB_SHARE_IS_IN_DFS;
2465 cFYI(1, ("DFS disabled (%d)",
2466 tcon->Flags));
2467 }
2468 }
2469 if (rc)
2470 goto remote_path_check;
2471 tcon->seal = volume_info->seal;
2472 write_lock(&cifs_tcp_ses_lock);
2473 list_add(&tcon->tcon_list, &pSesInfo->tcon_list);
2474 write_unlock(&cifs_tcp_ses_lock);
2475 }
2476
2477
2478
2479
2480
2481 tcon->retry = volume_info->retry;
2482 tcon->nocase = volume_info->nocase;
2483 tcon->local_lease = volume_info->local_lease;
2484 }
2485 if (pSesInfo) {
2486 if (pSesInfo->capabilities & CAP_LARGE_FILES)
2487 sb->s_maxbytes = MAX_LFS_FILESIZE;
2488 else
2489 sb->s_maxbytes = MAX_NON_LFS;
2490 }
2491
2492
2493 sb->s_time_gran = 100;
2494
2495 if (rc)
2496 goto remote_path_check;
2497
2498 cifs_sb->tcon = tcon;
2499
2500
2501 if (!tcon->ipc) {
2502 CIFSSMBQFSDeviceInfo(xid, tcon);
2503 CIFSSMBQFSAttributeInfo(xid, tcon);
2504 }
2505
2506
2507 if (tcon->ses->capabilities & CAP_UNIX)
2508
2509
2510 reset_cifs_unix_caps(xid, tcon, sb, volume_info);
2511 else
2512 tcon->unix_ext = 0;
2513
2514
2515 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) == 0)
2516 convert_delimiter(cifs_sb->prepath, CIFS_DIR_SEP(cifs_sb));
2517
2518 if ((tcon->unix_ext == 0) && (cifs_sb->rsize > (1024 * 127))) {
2519 cifs_sb->rsize = 1024 * 127;
2520 cFYI(DBG2, ("no very large read support, rsize now 127K"));
2521 }
2522 if (!(tcon->ses->capabilities & CAP_LARGE_WRITE_X))
2523 cifs_sb->wsize = min(cifs_sb->wsize,
2524 (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE));
2525 if (!(tcon->ses->capabilities & CAP_LARGE_READ_X))
2526 cifs_sb->rsize = min(cifs_sb->rsize,
2527 (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE));
2528
2529remote_path_check:
2530
2531 if (!rc && cifs_sb->prepathlen && tcon) {
2532
2533 full_path = cifs_build_path_to_root(cifs_sb);
2534 if (full_path == NULL) {
2535 rc = -ENOMEM;
2536 goto mount_fail_check;
2537 }
2538 rc = is_path_accessible(xid, tcon, cifs_sb, full_path);
2539 if (rc != -EREMOTE) {
2540 kfree(full_path);
2541 goto mount_fail_check;
2542 }
2543 kfree(full_path);
2544 }
2545
2546
2547 if (rc == -EREMOTE) {
2548#ifdef CONFIG_CIFS_DFS_UPCALL
2549 if (referral_walks_count > MAX_NESTED_LINKS) {
2550
2551
2552
2553
2554
2555
2556 rc = -ELOOP;
2557 goto mount_fail_check;
2558 }
2559
2560 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) == 0)
2561 convert_delimiter(cifs_sb->prepath,
2562 CIFS_DIR_SEP(cifs_sb));
2563 full_path = build_unc_path_to_root(volume_info, cifs_sb);
2564 if (IS_ERR(full_path)) {
2565 rc = PTR_ERR(full_path);
2566 goto mount_fail_check;
2567 }
2568
2569 cFYI(1, ("Getting referral for: %s", full_path));
2570 rc = get_dfs_path(xid, pSesInfo , full_path + 1,
2571 cifs_sb->local_nls, &num_referrals, &referrals,
2572 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
2573 if (!rc && num_referrals > 0) {
2574 char *fake_devname = NULL;
2575
2576 if (mount_data != mount_data_global)
2577 kfree(mount_data);
2578
2579 mount_data = cifs_compose_mount_options(
2580 cifs_sb->mountdata, full_path + 1,
2581 referrals, &fake_devname);
2582
2583 free_dfs_info_array(referrals, num_referrals);
2584 kfree(fake_devname);
2585 kfree(full_path);
2586
2587 if (IS_ERR(mount_data)) {
2588 rc = PTR_ERR(mount_data);
2589 mount_data = NULL;
2590 goto mount_fail_check;
2591 }
2592
2593 if (tcon)
2594 cifs_put_tcon(tcon);
2595 else if (pSesInfo)
2596 cifs_put_smb_ses(pSesInfo);
2597
2598 cleanup_volume_info(&volume_info);
2599 referral_walks_count++;
2600 goto try_mount_again;
2601 }
2602#else
2603 rc = -EOPNOTSUPP;
2604#endif
2605 }
2606
2607mount_fail_check:
2608
2609 if (rc) {
2610 if (mount_data != mount_data_global)
2611 kfree(mount_data);
2612
2613
2614 if (tcon)
2615 cifs_put_tcon(tcon);
2616 else if (pSesInfo)
2617 cifs_put_smb_ses(pSesInfo);
2618 else
2619 cifs_put_tcp_session(srvTcp);
2620 goto out;
2621 }
2622
2623
2624
2625
2626
2627out:
2628
2629 cleanup_volume_info(&volume_info);
2630 FreeXid(xid);
2631 return rc;
2632}
2633
2634int
2635CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
2636 const char *tree, struct cifsTconInfo *tcon,
2637 const struct nls_table *nls_codepage)
2638{
2639 struct smb_hdr *smb_buffer;
2640 struct smb_hdr *smb_buffer_response;
2641 TCONX_REQ *pSMB;
2642 TCONX_RSP *pSMBr;
2643 unsigned char *bcc_ptr;
2644 int rc = 0;
2645 int length, bytes_left;
2646 __u16 count;
2647
2648 if (ses == NULL)
2649 return -EIO;
2650
2651 smb_buffer = cifs_buf_get();
2652 if (smb_buffer == NULL)
2653 return -ENOMEM;
2654
2655 smb_buffer_response = smb_buffer;
2656
2657 header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX,
2658 NULL , 4 );
2659
2660 smb_buffer->Mid = GetNextMid(ses->server);
2661 smb_buffer->Uid = ses->Suid;
2662 pSMB = (TCONX_REQ *) smb_buffer;
2663 pSMBr = (TCONX_RSP *) smb_buffer_response;
2664
2665 pSMB->AndXCommand = 0xFF;
2666 pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO);
2667 bcc_ptr = &pSMB->Password[0];
2668 if ((ses->server->secMode) & SECMODE_USER) {
2669 pSMB->PasswordLength = cpu_to_le16(1);
2670 *bcc_ptr = 0;
2671 bcc_ptr++;
2672
2673 } else {
2674 pSMB->PasswordLength = cpu_to_le16(CIFS_SESS_KEY_SIZE);
2675
2676
2677
2678
2679
2680
2681#ifdef CONFIG_CIFS_WEAK_PW_HASH
2682 if ((extended_security & CIFSSEC_MAY_LANMAN) &&
2683 (ses->server->secType == LANMAN))
2684 calc_lanman_hash(tcon->password, ses->server->cryptKey,
2685 ses->server->secMode &
2686 SECMODE_PW_ENCRYPT ? true : false,
2687 bcc_ptr);
2688 else
2689#endif
2690 SMBNTencrypt(tcon->password, ses->server->cryptKey,
2691 bcc_ptr);
2692
2693 bcc_ptr += CIFS_SESS_KEY_SIZE;
2694 if (ses->capabilities & CAP_UNICODE) {
2695
2696 *bcc_ptr = 0;
2697 bcc_ptr++;
2698 }
2699 }
2700
2701 if (ses->server->secMode &
2702 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2703 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2704
2705 if (ses->capabilities & CAP_STATUS32) {
2706 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2707 }
2708 if (ses->capabilities & CAP_DFS) {
2709 smb_buffer->Flags2 |= SMBFLG2_DFS;
2710 }
2711 if (ses->capabilities & CAP_UNICODE) {
2712 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2713 length =
2714 cifs_strtoUCS((__le16 *) bcc_ptr, tree,
2715 6 *
2716 ( + 256 ), nls_codepage);
2717 bcc_ptr += 2 * length;
2718 bcc_ptr += 2;
2719 } else {
2720 strcpy(bcc_ptr, tree);
2721 bcc_ptr += strlen(tree) + 1;
2722 }
2723 strcpy(bcc_ptr, "?????");
2724 bcc_ptr += strlen("?????");
2725 bcc_ptr += 1;
2726 count = bcc_ptr - &pSMB->Password[0];
2727 pSMB->hdr.smb_buf_length += count;
2728 pSMB->ByteCount = cpu_to_le16(count);
2729
2730 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length,
2731 CIFS_STD_OP);
2732
2733
2734 if ((rc == 0) && (tcon != NULL)) {
2735 bool is_unicode;
2736
2737 tcon->tidStatus = CifsGood;
2738 tcon->need_reconnect = false;
2739 tcon->tid = smb_buffer_response->Tid;
2740 bcc_ptr = pByteArea(smb_buffer_response);
2741 bytes_left = BCC(smb_buffer_response);
2742 length = strnlen(bcc_ptr, bytes_left - 2);
2743 if (smb_buffer->Flags2 & SMBFLG2_UNICODE)
2744 is_unicode = true;
2745 else
2746 is_unicode = false;
2747
2748
2749
2750 if (length == 3) {
2751 if ((bcc_ptr[0] == 'I') && (bcc_ptr[1] == 'P') &&
2752 (bcc_ptr[2] == 'C')) {
2753 cFYI(1, ("IPC connection"));
2754 tcon->ipc = 1;
2755 }
2756 } else if (length == 2) {
2757 if ((bcc_ptr[0] == 'A') && (bcc_ptr[1] == ':')) {
2758
2759 cFYI(1, ("disk share connection"));
2760 }
2761 }
2762 bcc_ptr += length + 1;
2763 bytes_left -= (length + 1);
2764 strncpy(tcon->treeName, tree, MAX_TREE_SIZE);
2765
2766
2767 kfree(tcon->nativeFileSystem);
2768 tcon->nativeFileSystem = cifs_strndup_from_ucs(bcc_ptr,
2769 bytes_left, is_unicode,
2770 nls_codepage);
2771
2772 cFYI(1, ("nativeFileSystem=%s", tcon->nativeFileSystem));
2773
2774 if ((smb_buffer_response->WordCount == 3) ||
2775 (smb_buffer_response->WordCount == 7))
2776
2777 tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
2778 else
2779 tcon->Flags = 0;
2780 cFYI(1, ("Tcon flags: 0x%x ", tcon->Flags));
2781 } else if ((rc == 0) && tcon == NULL) {
2782
2783 ses->ipc_tid = smb_buffer_response->Tid;
2784 }
2785
2786 cifs_buf_release(smb_buffer);
2787 return rc;
2788}
2789
2790int
2791cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
2792{
2793 int rc = 0;
2794 char *tmp;
2795
2796 if (cifs_sb->tcon)
2797 cifs_put_tcon(cifs_sb->tcon);
2798
2799 cifs_sb->tcon = NULL;
2800 tmp = cifs_sb->prepath;
2801 cifs_sb->prepathlen = 0;
2802 cifs_sb->prepath = NULL;
2803 kfree(tmp);
2804
2805 return rc;
2806}
2807
2808int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
2809 struct nls_table *nls_info)
2810{
2811 int rc = 0;
2812 int first_time = 0;
2813 struct TCP_Server_Info *server = pSesInfo->server;
2814
2815
2816 if (server->maxBuf == 0) {
2817 rc = CIFSSMBNegotiate(xid, pSesInfo);
2818 if (rc == -EAGAIN) {
2819
2820 rc = CIFSSMBNegotiate(xid, pSesInfo);
2821 if (rc == -EAGAIN)
2822 rc = -EHOSTDOWN;
2823 }
2824 if (rc == 0) {
2825 spin_lock(&GlobalMid_Lock);
2826 if (server->tcpStatus != CifsExiting)
2827 server->tcpStatus = CifsGood;
2828 else
2829 rc = -EHOSTDOWN;
2830 spin_unlock(&GlobalMid_Lock);
2831
2832 }
2833 first_time = 1;
2834 }
2835
2836 if (rc)
2837 goto ss_err_exit;
2838
2839 pSesInfo->flags = 0;
2840 pSesInfo->capabilities = server->capabilities;
2841 if (linuxExtEnabled == 0)
2842 pSesInfo->capabilities &= (~CAP_UNIX);
2843
2844 cFYI(1, ("Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d",
2845 server->secMode, server->capabilities, server->timeAdj));
2846
2847 rc = CIFS_SessSetup(xid, pSesInfo, first_time, nls_info);
2848 if (rc) {
2849 cERROR(1, ("Send error in SessSetup = %d", rc));
2850 } else {
2851 cFYI(1, ("CIFS Session Established successfully"));
2852 spin_lock(&GlobalMid_Lock);
2853 pSesInfo->status = CifsGood;
2854 pSesInfo->need_reconnect = false;
2855 spin_unlock(&GlobalMid_Lock);
2856 }
2857
2858ss_err_exit:
2859 return rc;
2860}
2861
2862