Merge git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6
[sfrench/cifs-2.6.git] / fs / cifs / connect.c
index f58fef5878c3db87445d88dc311f7c4a5697cd03..19ee11f7f35ad6188207d25edccb0af3b8cdad11 100644 (file)
@@ -351,7 +351,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
 
        current->flags |= PF_MEMALLOC;
        server->tsk = current;  /* save process info to wake at shutdown */
-       cFYI(1, ("Demultiplex PID: %d", current->pid));
+       cFYI(1, ("Demultiplex PID: %d", task_pid_nr(current)));
        write_lock(&GlobalSMBSeslock);
        atomic_inc(&tcpSesAllocCount);
        length = tcpSesAllocCount.counter;
@@ -415,7 +415,10 @@ incomplete_rcv:
                        msleep(1); /* minimum sleep to prevent looping
                                allowing socket to clear and app threads to set
                                tcpStatus CifsNeedReconnect if server hung */
-                       continue;
+                       if (pdu_length < 4)
+                               goto incomplete_rcv;
+                       else
+                               continue;
                } else if (length <= 0) {
                        if (server->tcpStatus == CifsNew) {
                                cFYI(1, ("tcp session abend after SMBnegprot"));
@@ -439,7 +442,6 @@ incomplete_rcv:
                        cFYI(1, ("less than four bytes received (%d bytes)",
                              length));
                        pdu_length -= length;
-                       cifs_reconnect(server);
                        msleep(1);
                        goto incomplete_rcv;
                }
@@ -544,6 +546,7 @@ incomplete_rcv:
                                              allowing socket to clear and app
                                              threads to set tcpStatus
                                              CifsNeedReconnect if server hung*/
+                               length = 0;
                                continue;
                        } else if (length <= 0) {
                                cERROR(1, ("Received no data, expecting %d",
@@ -674,9 +677,8 @@ multi_t2_fnd:
                server->ssocket = NULL;
        }
        /* buffer usuallly freed in free_mid - need to free it here on exit */
-       if (bigbuf != NULL)
-               cifs_buf_release(bigbuf);
-       if (smallbuf != NULL)
+       cifs_buf_release(bigbuf);
+       if (smallbuf) /* no sense logging a debug message if NULL */
                cifs_small_buf_release(smallbuf);
 
        read_lock(&GlobalSMBSeslock);
@@ -1470,7 +1472,7 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
        if (psin_server->sin_port) { /* user overrode default port */
                rc = (*csocket)->ops->connect(*csocket,
                                (struct sockaddr *) psin_server,
-                               sizeof (struct sockaddr_in), 0);
+                               sizeof(struct sockaddr_in), 0);
                if (rc >= 0)
                        connected = 1;
        }
@@ -1486,7 +1488,7 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
 
                        rc = (*csocket)->ops->connect(*csocket,
                                        (struct sockaddr *) psin_server,
-                                       sizeof (struct sockaddr_in), 0);
+                                       sizeof(struct sockaddr_in), 0);
                        if (rc >= 0)
                                connected = 1;
                }
@@ -1495,7 +1497,7 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
                psin_server->sin_port = htons(RFC1001_PORT);
                rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
                                              psin_server,
-                                             sizeof (struct sockaddr_in), 0);
+                                             sizeof(struct sockaddr_in), 0);
                if (rc >= 0)
                        connected = 1;
        }
@@ -1603,7 +1605,7 @@ ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket)
        if (psin_server->sin6_port) { /* user overrode default port */
                rc = (*csocket)->ops->connect(*csocket,
                                (struct sockaddr *) psin_server,
-                               sizeof (struct sockaddr_in6), 0);
+                               sizeof(struct sockaddr_in6), 0);
                if (rc >= 0)
                        connected = 1;
        }
@@ -1619,7 +1621,7 @@ ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket)
 
                        rc = (*csocket)->ops->connect(*csocket,
                                        (struct sockaddr *) psin_server,
-                                       sizeof (struct sockaddr_in6), 0);
+                                       sizeof(struct sockaddr_in6), 0);
                        if (rc >= 0)
                                connected = 1;
                }
@@ -1627,7 +1629,7 @@ ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket)
        if (!connected) {
                psin_server->sin6_port = htons(RFC1001_PORT);
                rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
-                                psin_server, sizeof (struct sockaddr_in6), 0);
+                                psin_server, sizeof(struct sockaddr_in6), 0);
                if (rc >= 0)
                        connected = 1;
        }
@@ -1743,7 +1745,16 @@ void reset_cifs_unix_caps(int xid, struct cifsTconInfo *tcon,
                        cFYI(1, ("very large write cap"));
 #endif /* CIFS_DEBUG2 */
                if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) {
-                       cFYI(1, ("setting capabilities failed"));
+                       if (vol_info == NULL) {
+                               cFYI(1, ("resetting capabilities failed"));
+                       } else
+                               cERROR(1, ("Negotiating Unix capabilities "
+                                          "with the server failed.  Consider "
+                                          "mounting with the Unix Extensions\n"
+                                          "disabled, if problems are found, "
+                                          "by specifying the nounix mount "
+                                          "option."));
+
                }
        }
 }
@@ -1902,8 +1913,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
                        return rc;
                }
 
-               srvTcp = kmalloc(sizeof (struct TCP_Server_Info), GFP_KERNEL);
-               if (srvTcp == NULL) {
+               srvTcp = kzalloc(sizeof(struct TCP_Server_Info), GFP_KERNEL);
+               if (!srvTcp) {
                        rc = -ENOMEM;
                        sock_release(csocket);
                        kfree(volume_info.UNC);
@@ -1912,9 +1923,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
                        FreeXid(xid);
                        return rc;
                } else {
-                       memset(srvTcp, 0, sizeof (struct TCP_Server_Info));
                        memcpy(&srvTcp->addr.sockAddr, &sin_server,
-                               sizeof (struct sockaddr_in));
+                               sizeof(struct sockaddr_in));
                        atomic_set(&srvTcp->inFlight, 0);
                        /* BB Add code for ipv6 case too */
                        srvTcp->ssocket = csocket;
@@ -2166,8 +2176,18 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
                                                if (tsk)
                                                        kthread_stop(tsk);
                                        }
-                               } else
+                               } else {
                                        cFYI(1, ("No session or bad tcon"));
+                                       if ((pSesInfo->server) &&
+                                           (pSesInfo->server->tsk)) {
+                                               struct task_struct *tsk;
+                                               force_sig(SIGKILL,
+                                                       pSesInfo->server->tsk);
+                                               tsk = pSesInfo->server->tsk;
+                                               if (tsk)
+                                                       kthread_stop(tsk);
+                                       }
+                               }
                                sesInfoFree(pSesInfo);
                                /* pSesInfo = NULL; */
                        }
@@ -2178,8 +2198,10 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
                tcon->ses = pSesInfo;
 
                /* do not care if following two calls succeed - informational */
-               CIFSSMBQFSDeviceInfo(xid, tcon);
-               CIFSSMBQFSAttributeInfo(xid, tcon);
+               if (!tcon->ipc) {
+                       CIFSSMBQFSDeviceInfo(xid, tcon);
+                       CIFSSMBQFSAttributeInfo(xid, tcon);
+               }
 
                /* tell server which Unix caps we support */
                if (tcon->ses->capabilities & CAP_UNIX)
@@ -2519,8 +2541,7 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
 sesssetup_nomem:       /* do not return an error on nomem for the info strings,
                           since that could make reconnection harder, and
                           reconnection might be needed to free memory */
-       if (smb_buffer)
-               cifs_buf_release(smb_buffer);
+       cifs_buf_release(smb_buffer);
 
        return rc;
 }
@@ -2540,7 +2561,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
        int remaining_words = 0;
        int bytes_returned = 0;
        int len;
-       int SecurityBlobLength = sizeof (NEGOTIATE_MESSAGE);
+       int SecurityBlobLength = sizeof(NEGOTIATE_MESSAGE);
        PNEGOTIATE_MESSAGE SecurityBlob;
        PCHALLENGE_MESSAGE SecurityBlob2;
        __u32 negotiate_flags, capabilities;
@@ -2858,15 +2879,14 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
                rc = -EIO;
        }
 
-       if (smb_buffer)
-               cifs_buf_release(smb_buffer);
+       cifs_buf_release(smb_buffer);
 
        return rc;
 }
 static int
 CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
-               char *ntlm_session_key, int ntlmv2_flag,
-               const struct nls_table *nls_codepage)
+                       char *ntlm_session_key, int ntlmv2_flag,
+                       const struct nls_table *nls_codepage)
 {
        struct smb_hdr *smb_buffer;
        struct smb_hdr *smb_buffer_response;
@@ -2879,7 +2899,7 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
        int remaining_words = 0;
        int bytes_returned = 0;
        int len;
-       int SecurityBlobLength = sizeof (AUTHENTICATE_MESSAGE);
+       int SecurityBlobLength = sizeof(AUTHENTICATE_MESSAGE);
        PAUTHENTICATE_MESSAGE SecurityBlob;
        __u32 negotiate_flags, capabilities;
        __u16 count;
@@ -2894,8 +2914,8 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
                return -ENOMEM;
        }
        smb_buffer_response = smb_buffer;
-       pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
-       pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response;
+       pSMB = (SESSION_SETUP_ANDX *)smb_buffer;
+       pSMBr = (SESSION_SETUP_ANDX *)smb_buffer_response;
 
        /* send SMBsessionSetup here */
        header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
@@ -2914,7 +2934,7 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
                smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
 
        capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
-           CAP_EXTENDED_SECURITY;
+                       CAP_EXTENDED_SECURITY;
        if (ses->capabilities & CAP_UNICODE) {
                smb_buffer->Flags2 |= SMBFLG2_UNICODE;
                capabilities |= CAP_UNICODE;
@@ -2929,15 +2949,14 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
        }
        pSMB->req.Capabilities = cpu_to_le32(capabilities);
 
-       bcc_ptr = (char *) &pSMB->req.SecurityBlob;
-       SecurityBlob = (PAUTHENTICATE_MESSAGE) bcc_ptr;
+       bcc_ptr = (char *)&pSMB->req.SecurityBlob;
+       SecurityBlob = (PAUTHENTICATE_MESSAGE)bcc_ptr;
        strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
        SecurityBlob->MessageType = NtLmAuthenticate;
        bcc_ptr += SecurityBlobLength;
-       negotiate_flags =
-           NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_REQUEST_TARGET |
-           NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_TARGET_INFO |
-           0x80000000 | NTLMSSP_NEGOTIATE_128;
+       negotiate_flags = NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_REQUEST_TARGET |
+                       NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_TARGET_INFO |
+                       0x80000000 | NTLMSSP_NEGOTIATE_128;
        if (sign_CIFS_PDUs)
                negotiate_flags |= /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN |*/ NTLMSSP_NEGOTIATE_SIGN;
        if (ntlmv2_flag)
@@ -3088,12 +3107,11 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
        rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
                         &bytes_returned, 1);
        if (rc) {
-/*    rc = map_smb_to_linux_error(smb_buffer_response);  *//* done in SendReceive now */
-       } else if ((smb_buffer_response->WordCount == 3)
-                  || (smb_buffer_response->WordCount == 4)) {
+/*   rc = map_smb_to_linux_error(smb_buffer_response) done in SendReceive now */
+       } else if ((smb_buffer_response->WordCount == 3) ||
+                  (smb_buffer_response->WordCount == 4)) {
                __u16 action = le16_to_cpu(pSMBr->resp.Action);
-               __u16 blob_len =
-                   le16_to_cpu(pSMBr->resp.SecurityBlobLength);
+               __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
                if (action & GUEST_LOGIN)
                        cFYI(1, (" Guest login")); /* BB Should we set anything
                                                         in SesInfo struct ? */
@@ -3247,28 +3265,24 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
                                                bcc_ptr[0] = 0;
                                                bcc_ptr++;
                                        } else
-                                               cFYI(1,
-                                                    ("field of length %d "
+                                               cFYI(1, ("field of length %d "
                                                   "extends beyond end of smb ",
                                                      len));
                                }
                        } else {
-                               cERROR(1,
-                                      (" Security Blob extends beyond end "
+                               cERROR(1, ("Security Blob extends beyond end "
                                        "of SMB"));
                        }
                } else {
                        cERROR(1, ("No session structure passed in."));
                }
        } else {
-               cERROR(1,
-                      (" Invalid Word count %d: ",
+               cERROR(1, ("Invalid Word count %d: ",
                        smb_buffer_response->WordCount));
                rc = -EIO;
        }
 
-       if (smb_buffer)
-               cifs_buf_release(smb_buffer);
+       cifs_buf_release(smb_buffer);
 
        return rc;
 }
@@ -3377,6 +3391,18 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
                bcc_ptr = pByteArea(smb_buffer_response);
                length = strnlen(bcc_ptr, BCC(smb_buffer_response) - 2);
                /* skip service field (NB: this field is always ASCII) */
+               if (length == 3) {
+                       if ((bcc_ptr[0] == 'I') && (bcc_ptr[1] == 'P') &&
+                           (bcc_ptr[2] == 'C')) {
+                               cFYI(1, ("IPC connection"));
+                               tcon->ipc = 1;
+                       }
+               } else if (length == 2) {
+                       if ((bcc_ptr[0] == 'A') && (bcc_ptr[1] == ':')) {
+                               /* the most common case */
+                               cFYI(1, ("disk share connection"));
+                       }
+               }
                bcc_ptr += length + 1;
                strncpy(tcon->treeName, tree, MAX_TREE_SIZE);
                if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
@@ -3387,9 +3413,11 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
                                kfree(tcon->nativeFileSystem);
                                tcon->nativeFileSystem =
                                    kzalloc(length + 2, GFP_KERNEL);
-                               cifs_strfromUCS_le(tcon->nativeFileSystem,
-                                                  (__le16 *) bcc_ptr,
-                                                  length, nls_codepage);
+                               if (tcon->nativeFileSystem)
+                                       cifs_strfromUCS_le(
+                                               tcon->nativeFileSystem,
+                                               (__le16 *) bcc_ptr,
+                                               length, nls_codepage);
                                bcc_ptr += 2 * length;
                                bcc_ptr[0] = 0; /* null terminate the string */
                                bcc_ptr[1] = 0;
@@ -3404,8 +3432,9 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
                                kfree(tcon->nativeFileSystem);
                                tcon->nativeFileSystem =
                                    kzalloc(length + 1, GFP_KERNEL);
-                               strncpy(tcon->nativeFileSystem, bcc_ptr,
-                                       length);
+                               if (tcon->nativeFileSystem)
+                                       strncpy(tcon->nativeFileSystem, bcc_ptr,
+                                               length);
                        }
                        /* else do not bother copying these information fields*/
                }
@@ -3421,8 +3450,7 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
                ses->ipc_tid = smb_buffer_response->Tid;
        }
 
-       if (smb_buffer)
-               cifs_buf_release(smb_buffer);
+       cifs_buf_release(smb_buffer);
        return rc;
 }