📄 cifssmb.c
字号:
CIFSFindSingle(const int xid, struct cifsTconInfo *tcon, const char *searchName, FILE_ALL_INFO * findData, const struct nls_table *nls_codepage){/* level 257 SMB_ */ TRANSACTION2_FFIRST_REQ *pSMB = NULL; TRANSACTION2_FFIRST_RSP *pSMBr = NULL; int rc = 0; int bytes_returned; int name_len; __u16 params, byte_count; cFYI(1, ("In FindUnique"));findUniqueRetry: rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, (void **) &pSMBr); if (rc) return rc; if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { name_len = cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530 /* find define for this maxpathcomponent */ , nls_codepage); name_len++; /* trailing null */ name_len *= 2; } else { /* BB improve the check for buffer overruns BB */ name_len = strnlen(searchName, 530); name_len++; /* trailing null */ strncpy(pSMB->FileName, searchName, name_len); } params = 12 + name_len /* includes null */ ; pSMB->TotalDataCount = 0; /* no EAs */ pSMB->MaxParameterCount = cpu_to_le16(2); pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */ pSMB->MaxSetupCount = 0; pSMB->Reserved = 0; pSMB->Flags = 0; pSMB->Timeout = 0; pSMB->Reserved2 = 0; pSMB->ParameterOffset = cpu_to_le16( offsetof(struct smb_com_transaction2_ffirst_req,InformationLevel) - 4); pSMB->DataCount = 0; pSMB->DataOffset = 0; pSMB->SetupCount = 1; /* one byte, no need to le convert */ pSMB->Reserved3 = 0; pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST); byte_count = params + 1 /* pad */ ; pSMB->TotalParameterCount = cpu_to_le16(params); pSMB->ParameterCount = pSMB->TotalParameterCount; pSMB->SearchAttributes = cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY); pSMB->SearchCount = cpu_to_le16(16); /* BB increase */ pSMB->SearchFlags = cpu_to_le16(1); pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO); pSMB->SearchStorageType = 0; /* BB what should we set this to? BB */ pSMB->hdr.smb_buf_length += byte_count; pSMB->ByteCount = cpu_to_le16(byte_count); rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, (struct smb_hdr *) pSMBr, &bytes_returned, 0); if (rc) { cFYI(1, ("Send error in FindFileDirInfo = %d", rc)); } else { /* decode response */ /* BB fill in */ } if (pSMB) cifs_buf_release(pSMB); if (rc == -EAGAIN) goto findUniqueRetry; return rc;}intCIFSFindFirst(const int xid, struct cifsTconInfo *tcon, const char *searchName, FILE_DIRECTORY_INFO * findData, T2_FFIRST_RSP_PARMS * findParms, const struct nls_table *nls_codepage, int *pUnicodeFlag, int *pUnixFlag){/* level 257 SMB_ */ TRANSACTION2_FFIRST_REQ *pSMB = NULL; TRANSACTION2_FFIRST_RSP *pSMBr = NULL; char *response_data; int rc = 0; int bytes_returned; int name_len; __u16 params, byte_count; cFYI(1, ("In FindFirst"));findFirstRetry: rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, (void **) &pSMBr); if (rc) return rc; if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { name_len = cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530 /* find define for this maxpathcomponent */ , nls_codepage); name_len++; /* trailing null */ name_len *= 2; } else { /* BB improve the check for buffer overruns BB */ name_len = strnlen(searchName, 530); name_len++; /* trailing null */ strncpy(pSMB->FileName, searchName, name_len); } params = 12 + name_len /* includes null */ ; pSMB->TotalDataCount = 0; /* no EAs */ pSMB->MaxParameterCount = cpu_to_le16(10); pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00); pSMB->MaxSetupCount = 0; pSMB->Reserved = 0; pSMB->Flags = 0; pSMB->Timeout = 0; pSMB->Reserved2 = 0; byte_count = params + 1 /* pad */ ; pSMB->TotalParameterCount = cpu_to_le16(params); pSMB->ParameterCount = pSMB->TotalParameterCount; pSMB->ParameterOffset = cpu_to_le16(offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes) - 4); pSMB->DataCount = 0; pSMB->DataOffset = 0; pSMB->SetupCount = 1; /* one byte no need to make endian neutral */ pSMB->Reserved3 = 0; pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST); pSMB->SearchAttributes = cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY); pSMB->SearchCount = cpu_to_le16(CIFS_MAX_MSGSIZE / sizeof (FILE_DIRECTORY_INFO)); /* should this be shrunk even more ? */ pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME); /* test for Unix extensions */ if (tcon->ses->capabilities & CAP_UNIX) { pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX); *pUnixFlag = TRUE; } else { pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO); *pUnixFlag = FALSE; } pSMB->SearchStorageType = 0; /* BB what should we set this to? It is not clear if it matters BB */ pSMB->hdr.smb_buf_length += byte_count; pSMB->ByteCount = cpu_to_le16(byte_count); rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, (struct smb_hdr *) pSMBr, &bytes_returned, 0); if (rc) { /* BB add logic to retry regular search if Unix search rejected unexpectedly by server */ cFYI(1, ("Error in FindFirst = %d", rc)); } else { /* decode response */ /* BB add safety checks for these memcpys */ if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) *pUnicodeFlag = TRUE; else *pUnicodeFlag = FALSE; memcpy(findParms, (char *) &pSMBr->hdr.Protocol + le16_to_cpu(pSMBr->ParameterOffset), sizeof (T2_FFIRST_RSP_PARMS)); response_data = (char *) &pSMBr->hdr.Protocol + le16_to_cpu(pSMBr->DataOffset); memcpy(findData, response_data, le16_to_cpu(pSMBr->DataCount)); } if (pSMB) cifs_buf_release(pSMB); if (rc == -EAGAIN) goto findFirstRetry; return rc;}intCIFSFindNext(const int xid, struct cifsTconInfo *tcon, FILE_DIRECTORY_INFO * findData, T2_FNEXT_RSP_PARMS * findParms, const __u16 searchHandle, char * resume_file_name, int name_len, __u32 resume_key, int *pUnicodeFlag, int *pUnixFlag){/* level 257 SMB_ */ TRANSACTION2_FNEXT_REQ *pSMB = NULL; TRANSACTION2_FNEXT_RSP *pSMBr = NULL; char *response_data; int rc = 0; int bytes_returned; __u16 params, byte_count; cFYI(1, ("In FindNext")); if(resume_file_name == NULL) { return -EIO; } rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, (void **) &pSMBr); if (rc) return rc; params = 14; /* includes 2 bytes of null string, converted to LE below */ byte_count = 0; pSMB->TotalDataCount = 0; /* no EAs */ pSMB->MaxParameterCount = cpu_to_le16(8); pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00); pSMB->MaxSetupCount = 0; pSMB->Reserved = 0; pSMB->Flags = 0; pSMB->Timeout = 0; pSMB->Reserved2 = 0; pSMB->ParameterOffset = cpu_to_le16(offsetof( struct smb_com_transaction2_fnext_req,SearchHandle) - 4); pSMB->DataCount = 0; pSMB->DataOffset = 0; pSMB->SetupCount = 1; pSMB->Reserved3 = 0; pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT); pSMB->SearchHandle = searchHandle; /* always kept as le */ findParms->SearchCount = 0; /* set to zero in case of error */ pSMB->SearchCount = cpu_to_le16(CIFS_MAX_MSGSIZE / sizeof (FILE_DIRECTORY_INFO)); /* test for Unix extensions */ if (tcon->ses->capabilities & CAP_UNIX) { pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX); *pUnixFlag = TRUE; } else { pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO); *pUnixFlag = FALSE; } pSMB->ResumeKey = resume_key; pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME); /* BB add check to make sure we do not cross end of smb */ if(name_len < CIFS_MAX_MSGSIZE) { memcpy(pSMB->ResumeFileName, resume_file_name, name_len); byte_count += name_len; } params += name_len; byte_count = params + 1 /* pad */ ; pSMB->TotalParameterCount = cpu_to_le16(params); pSMB->ParameterCount = pSMB->TotalParameterCount; /* BB improve error handling here */ pSMB->hdr.smb_buf_length += byte_count; pSMB->ByteCount = cpu_to_le16(byte_count); rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, (struct smb_hdr *) pSMBr, &bytes_returned, 0); if (rc) { if (rc == -EBADF) rc = 0; /* search probably was closed at end of search above */ else cFYI(1, ("FindNext returned = %d", rc)); } else { /* decode response */ /* BB add safety checks for these memcpys */ if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) *pUnicodeFlag = TRUE; else *pUnicodeFlag = FALSE; memcpy(findParms, (char *) &pSMBr->hdr.Protocol + le16_to_cpu(pSMBr->ParameterOffset), sizeof (T2_FNEXT_RSP_PARMS)); response_data = (char *) &pSMBr->hdr.Protocol + le16_to_cpu(pSMBr->DataOffset); memcpy(findData, response_data, le16_to_cpu(pSMBr->DataCount)); } if (pSMB) cifs_buf_release(pSMB); /* Note: On -EAGAIN error only caller can retry on handle based calls since file handle passed in no longer valid */ return rc;}intCIFSFindClose(const int xid, struct cifsTconInfo *tcon, const __u16 searchHandle){ int rc = 0; FINDCLOSE_REQ *pSMB = NULL; CLOSE_RSP *pSMBr = NULL; int bytes_returned; cFYI(1, ("In CIFSSMBFindClose")); rc = smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **) &pSMB, (void **) &pSMBr); /* no sense returning error if session restarted file handle has been closed */ if(rc == -EAGAIN) return 0; if (rc) return rc; pSMB->FileID = searchHandle; pSMB->ByteCount = 0; rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, (struct smb_hdr *) pSMBr, &bytes_returned, 0); if (rc) { cERROR(1, ("Send error in FindClose = %d", rc)); } if (pSMB) cifs_buf_release(pSMB); /* Since session is dead, search handle closed on server already */ if (rc == -EAGAIN) rc = 0; return rc;}intCIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses, const unsigned char *searchName, unsigned char **targetUNCs, unsigned int *number_of_UNC_in_array, const struct nls_table *nls_codepage){/* TRANS2_GET_DFS_REFERRAL */ TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL; TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL; struct dfs_referral_level_3 * referrals = NULL; int rc = 0; int bytes_returned; int name_len; unsigned int i; char * temp; __u16 params, byte_count; *number_of_UNC_in_array = 0; *targetUNCs = NULL; cFYI(1, ("In GetDFSRefer the path %s", searchName)); if (ses == NULL) return -ENODEV;getDFSRetry: rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB, (void **) &pSMBr); if (rc) return rc; pSMB->hdr.Tid = ses->ipc_tid; pSMB->hdr.Uid = ses->Suid; if (ses->capabilities & CAP_STATUS32) { pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS; } if (ses->capabilities & CAP_DFS) { pSMB->hdr.Flags2 |= SMBFLG2_DFS; } if (ses->capabilities & CAP_UNICODE) { pSMB->hdr.Flags2 |= SMBFLG2_UNICODE; name_len = cifs_strtoUCS((wchar_t *) pSMB->RequestFileName, searchName, 530 /* find define for this maxpathcomponent */ , nls_codepage); name_len++; /* trailing null */ name_len *= 2; } else { /* BB improve the check for buffer overruns BB */ name_len = strnlen(searchName, 530); name_len++; /* trailing null */ strncpy(pSMB->RequestFileName, searchName, name_len); } params = 2 /* level */ + name_len /*includes null */ ; pSMB->TotalDataCount = 0; pSMB->DataCount = 0; pSMB->DataOffset = 0; pSMB->MaxParameterCount = 0; pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */ pSMB->MaxSetupCount = 0; pSMB->Reserved = 0; pSMB->Flags = 0; pSMB->Timeout = 0; pSMB->Reserved2 = 0; pSMB->ParameterOffset = cpu_to_le16(offsetof( struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4); pSMB->SetupCount = 1; pSMB->Reserved3 = 0; pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL); byte_count = params + 3 /* pad */ ; pSMB->ParameterCount = cpu_to_le16(params); pSMB->TotalParameterCount = pSMB->ParameterCount; pSMB->MaxReferralLevel = cpu_to_le16(3); pSMB->hdr.smb_buf_length += byte_count; pSMB->ByteCount = cpu_to_le16(byte_count); rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB, (struct smb_hdr *) pSMBr, &bytes_returned, 0); if (rc) { cFYI(1, ("Send error in GetDFSRefer = %d", rc)); } else { /* decode response *//* BB Add logic to parse referrals here */ __u16 data_offset = le16_to_cpu(pSMBr->DataOffset); __u16 data_count = le16_to_cpu(pSMBr->DataCount); cFYI(1, ("Decoding GetDFSRefer response. BCC: %d Offset %d", pSMBr->ByteCount, data_offset)); if ((pSMBr->ByteCount < 17) || (data_offset > 512)) /* BB also check enough total bytes returned */ rc = -EIO; /* bad smb */ else { referrals = (struct dfs_referral_level_3 *) (8 /* sizeof start of data block */ + data_offset + (char *) &pSMBr->hdr.Protocol); cFYI(1,("num_referrals: %d dfs flags: 0x%x ... \nfor referral one refer size: 0x%x srv type: 0x%x refer flags: 0x%x ttl: 0x%x", le16_to_cpu(pSMBr->NumberOfReferrals),le16_to_cpu(pSMBr->DFSFlags), le16_to_cpu(referrals->ReferralSize),le16_to_cpu(referrals->ServerType),le16_to_cpu(referrals->ReferralFlags),le16_to_cpu(referrals->TimeToLive))); /* BB This field is actually two bytes in from start of data block so we could do safety check that DataBlock begins at address of pSMBr->NumberOfReferrals */ *number_of_UNC_in_array = le16_to_cpu(pSMBr->NumberOfReferrals); /* BB Fix below so can return more than one referral */ if(*number_of_UNC_in_array > 1) *number_of_UNC_in_array = 1; /* get the length of the strings describing refs */ name_len = 0; for(i=0;i<*number_of_UNC_in_array;i++) { /* make sure that DfsPathOffset not past end */ __u16 offse
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -