@@ -534,6 +534,146 @@ CIFSSMBNegotiate(const unsigned int xid,
534534 return rc ;
535535}
536536
537+ /*
538+ * Issue a TREE_CONNECT request.
539+ */
540+ int
541+ CIFSTCon (const unsigned int xid , struct cifs_ses * ses ,
542+ const char * tree , struct cifs_tcon * tcon ,
543+ const struct nls_table * nls_codepage )
544+ {
545+ struct smb_hdr * smb_buffer ;
546+ struct smb_hdr * smb_buffer_response ;
547+ TCONX_REQ * pSMB ;
548+ TCONX_RSP * pSMBr ;
549+ unsigned char * bcc_ptr ;
550+ int rc = 0 ;
551+ int length , in_len ;
552+ __u16 bytes_left , count ;
553+
554+ if (ses == NULL )
555+ return smb_EIO (smb_eio_trace_null_pointers );
556+
557+ smb_buffer = cifs_buf_get ();
558+ if (smb_buffer == NULL )
559+ return - ENOMEM ;
560+
561+ smb_buffer_response = smb_buffer ;
562+
563+ in_len = header_assemble (smb_buffer , SMB_COM_TREE_CONNECT_ANDX ,
564+ NULL /*no tid */ , 4 /*wct */ );
565+
566+ smb_buffer -> Mid = get_next_mid (ses -> server );
567+ smb_buffer -> Uid = ses -> Suid ;
568+ pSMB = (TCONX_REQ * ) smb_buffer ;
569+ pSMBr = (TCONX_RSP * ) smb_buffer_response ;
570+
571+ pSMB -> AndXCommand = 0xFF ;
572+ pSMB -> Flags = cpu_to_le16 (TCON_EXTENDED_SECINFO );
573+ bcc_ptr = & pSMB -> Password [0 ];
574+
575+ pSMB -> PasswordLength = cpu_to_le16 (1 ); /* minimum */
576+ * bcc_ptr = 0 ; /* password is null byte */
577+ bcc_ptr ++ ; /* skip password */
578+ /* already aligned so no need to do it below */
579+
580+ if (ses -> server -> sign )
581+ smb_buffer -> Flags2 |= SMBFLG2_SECURITY_SIGNATURE ;
582+
583+ if (ses -> capabilities & CAP_STATUS32 )
584+ smb_buffer -> Flags2 |= SMBFLG2_ERR_STATUS ;
585+
586+ if (ses -> capabilities & CAP_DFS )
587+ smb_buffer -> Flags2 |= SMBFLG2_DFS ;
588+
589+ if (ses -> capabilities & CAP_UNICODE ) {
590+ smb_buffer -> Flags2 |= SMBFLG2_UNICODE ;
591+ length =
592+ cifs_strtoUTF16 ((__le16 * ) bcc_ptr , tree ,
593+ 6 /* max utf8 char length in bytes */ *
594+ (/* server len*/ + 256 /* share len */ ), nls_codepage );
595+ bcc_ptr += 2 * length ; /* convert num 16 bit words to bytes */
596+ bcc_ptr += 2 ; /* skip trailing null */
597+ } else { /* ASCII */
598+ strcpy (bcc_ptr , tree );
599+ bcc_ptr += strlen (tree ) + 1 ;
600+ }
601+ strcpy (bcc_ptr , "?????" );
602+ bcc_ptr += strlen ("?????" );
603+ bcc_ptr += 1 ;
604+ count = bcc_ptr - & pSMB -> Password [0 ];
605+ in_len += count ;
606+ pSMB -> ByteCount = cpu_to_le16 (count );
607+
608+ rc = SendReceive (xid , ses , smb_buffer , in_len , smb_buffer_response ,
609+ & length , 0 );
610+
611+ /* above now done in SendReceive */
612+ if (rc == 0 ) {
613+ bool is_unicode ;
614+
615+ tcon -> tid = smb_buffer_response -> Tid ;
616+ bcc_ptr = pByteArea (smb_buffer_response );
617+ bytes_left = get_bcc (smb_buffer_response );
618+ length = strnlen (bcc_ptr , bytes_left - 2 );
619+ if (smb_buffer -> Flags2 & SMBFLG2_UNICODE )
620+ is_unicode = true;
621+ else
622+ is_unicode = false;
623+
624+
625+ /* skip service field (NB: this field is always ASCII) */
626+ if (length == 3 ) {
627+ if ((bcc_ptr [0 ] == 'I' ) && (bcc_ptr [1 ] == 'P' ) &&
628+ (bcc_ptr [2 ] == 'C' )) {
629+ cifs_dbg (FYI , "IPC connection\n" );
630+ tcon -> ipc = true;
631+ tcon -> pipe = true;
632+ }
633+ } else if (length == 2 ) {
634+ if ((bcc_ptr [0 ] == 'A' ) && (bcc_ptr [1 ] == ':' )) {
635+ /* the most common case */
636+ cifs_dbg (FYI , "disk share connection\n" );
637+ }
638+ }
639+ bcc_ptr += length + 1 ;
640+ bytes_left -= (length + 1 );
641+ strscpy (tcon -> tree_name , tree , sizeof (tcon -> tree_name ));
642+
643+ /* mostly informational -- no need to fail on error here */
644+ kfree (tcon -> nativeFileSystem );
645+ tcon -> nativeFileSystem = cifs_strndup_from_utf16 (bcc_ptr ,
646+ bytes_left , is_unicode ,
647+ nls_codepage );
648+
649+ cifs_dbg (FYI , "nativeFileSystem=%s\n" , tcon -> nativeFileSystem );
650+
651+ if ((smb_buffer_response -> WordCount == 3 ) ||
652+ (smb_buffer_response -> WordCount == 7 ))
653+ /* field is in same location */
654+ tcon -> Flags = le16_to_cpu (pSMBr -> OptionalSupport );
655+ else
656+ tcon -> Flags = 0 ;
657+ cifs_dbg (FYI , "Tcon flags: 0x%x\n" , tcon -> Flags );
658+
659+ /*
660+ * reset_cifs_unix_caps calls QFSInfo which requires
661+ * need_reconnect to be false, but we would not need to call
662+ * reset_caps if this were not a reconnect case so must check
663+ * need_reconnect flag here. The caller will also clear
664+ * need_reconnect when tcon was successful but needed to be
665+ * cleared earlier in the case of unix extensions reconnect
666+ */
667+ if (tcon -> need_reconnect && tcon -> unix_ext ) {
668+ cifs_dbg (FYI , "resetting caps for %s\n" , tcon -> tree_name );
669+ tcon -> need_reconnect = false;
670+ reset_cifs_unix_caps (xid , tcon , NULL , NULL );
671+ }
672+ }
673+ cifs_buf_release (smb_buffer );
674+ return rc ;
675+ }
676+
537677int
538678CIFSSMBTDis (const unsigned int xid , struct cifs_tcon * tcon )
539679{
0 commit comments