diff options
author | J. Bruce Fields <bfields@citi.umich.edu> | 2008-07-03 16:24:06 -0400 |
---|---|---|
committer | J. Bruce Fields <bfields@citi.umich.edu> | 2008-07-03 16:24:06 -0400 |
commit | e86322f611eef95aafaf726fd3965e5b211f1985 (patch) | |
tree | 28547e26df4fc6ae671dc8cc6912a53717e4db08 /fs/cifs/cifssmb.c | |
parent | b001a1b6aa960949a24c2cdc28257dfcc9428d74 (diff) | |
parent | 8948896c9e098c6fd31a6a698a598a7cbd7fa40e (diff) |
Merge branch 'for-bfields' of git://linux-nfs.org/~tomtucker/xprt-switch-2.6 into for-2.6.27
Diffstat (limited to 'fs/cifs/cifssmb.c')
-rw-r--r-- | fs/cifs/cifssmb.c | 339 |
1 files changed, 200 insertions, 139 deletions
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 95fbba4ea7d4..4511b708f0f3 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c | |||
@@ -81,6 +81,40 @@ static struct { | |||
81 | #endif /* CONFIG_CIFS_WEAK_PW_HASH */ | 81 | #endif /* CONFIG_CIFS_WEAK_PW_HASH */ |
82 | #endif /* CIFS_POSIX */ | 82 | #endif /* CIFS_POSIX */ |
83 | 83 | ||
84 | /* Allocates buffer into dst and copies smb string from src to it. | ||
85 | * caller is responsible for freeing dst if function returned 0. | ||
86 | * returns: | ||
87 | * on success - 0 | ||
88 | * on failure - errno | ||
89 | */ | ||
90 | static int | ||
91 | cifs_strncpy_to_host(char **dst, const char *src, const int maxlen, | ||
92 | const bool is_unicode, const struct nls_table *nls_codepage) | ||
93 | { | ||
94 | int plen; | ||
95 | |||
96 | if (is_unicode) { | ||
97 | plen = UniStrnlen((wchar_t *)src, maxlen); | ||
98 | *dst = kmalloc(plen + 2, GFP_KERNEL); | ||
99 | if (!*dst) | ||
100 | goto cifs_strncpy_to_host_ErrExit; | ||
101 | cifs_strfromUCS_le(*dst, (__le16 *)src, plen, nls_codepage); | ||
102 | } else { | ||
103 | plen = strnlen(src, maxlen); | ||
104 | *dst = kmalloc(plen + 2, GFP_KERNEL); | ||
105 | if (!*dst) | ||
106 | goto cifs_strncpy_to_host_ErrExit; | ||
107 | strncpy(*dst, src, plen); | ||
108 | } | ||
109 | (*dst)[plen] = 0; | ||
110 | (*dst)[plen+1] = 0; /* harmless for ASCII case, needed for Unicode */ | ||
111 | return 0; | ||
112 | |||
113 | cifs_strncpy_to_host_ErrExit: | ||
114 | cERROR(1, ("Failed to allocate buffer for string\n")); | ||
115 | return -ENOMEM; | ||
116 | } | ||
117 | |||
84 | 118 | ||
85 | /* Mark as invalid, all open files on tree connections since they | 119 | /* Mark as invalid, all open files on tree connections since they |
86 | were closed when session to server was lost */ | 120 | were closed when session to server was lost */ |
@@ -1166,6 +1200,20 @@ static __u16 convert_disposition(int disposition) | |||
1166 | return ofun; | 1200 | return ofun; |
1167 | } | 1201 | } |
1168 | 1202 | ||
1203 | static int | ||
1204 | access_flags_to_smbopen_mode(const int access_flags) | ||
1205 | { | ||
1206 | int masked_flags = access_flags & (GENERIC_READ | GENERIC_WRITE); | ||
1207 | |||
1208 | if (masked_flags == GENERIC_READ) | ||
1209 | return SMBOPEN_READ; | ||
1210 | else if (masked_flags == GENERIC_WRITE) | ||
1211 | return SMBOPEN_WRITE; | ||
1212 | |||
1213 | /* just go for read/write */ | ||
1214 | return SMBOPEN_READWRITE; | ||
1215 | } | ||
1216 | |||
1169 | int | 1217 | int |
1170 | SMBLegacyOpen(const int xid, struct cifsTconInfo *tcon, | 1218 | SMBLegacyOpen(const int xid, struct cifsTconInfo *tcon, |
1171 | const char *fileName, const int openDisposition, | 1219 | const char *fileName, const int openDisposition, |
@@ -1207,13 +1255,7 @@ OldOpenRetry: | |||
1207 | pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK); | 1255 | pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK); |
1208 | 1256 | ||
1209 | pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO); | 1257 | pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO); |
1210 | /* BB fixme add conversion for access_flags to bits 0 - 2 of mode */ | 1258 | pSMB->Mode = cpu_to_le16(access_flags_to_smbopen_mode(access_flags)); |
1211 | /* 0 = read | ||
1212 | 1 = write | ||
1213 | 2 = rw | ||
1214 | 3 = execute | ||
1215 | */ | ||
1216 | pSMB->Mode = cpu_to_le16(2); | ||
1217 | pSMB->Mode |= cpu_to_le16(0x40); /* deny none */ | 1259 | pSMB->Mode |= cpu_to_le16(0x40); /* deny none */ |
1218 | /* set file as system file if special file such | 1260 | /* set file as system file if special file such |
1219 | as fifo and server expecting SFU style and | 1261 | as fifo and server expecting SFU style and |
@@ -1247,7 +1289,7 @@ OldOpenRetry: | |||
1247 | } else { | 1289 | } else { |
1248 | /* BB verify if wct == 15 */ | 1290 | /* BB verify if wct == 15 */ |
1249 | 1291 | ||
1250 | /* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field BB */ | 1292 | /* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field*/ |
1251 | 1293 | ||
1252 | *netfid = pSMBr->Fid; /* cifs fid stays in le */ | 1294 | *netfid = pSMBr->Fid; /* cifs fid stays in le */ |
1253 | /* Let caller know file was created so we can set the mode. */ | 1295 | /* Let caller know file was created so we can set the mode. */ |
@@ -1686,7 +1728,7 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, | |||
1686 | { | 1728 | { |
1687 | int rc = 0; | 1729 | int rc = 0; |
1688 | LOCK_REQ *pSMB = NULL; | 1730 | LOCK_REQ *pSMB = NULL; |
1689 | LOCK_RSP *pSMBr = NULL; | 1731 | /* LOCK_RSP *pSMBr = NULL; */ /* No response data other than rc to parse */ |
1690 | int bytes_returned; | 1732 | int bytes_returned; |
1691 | int timeout = 0; | 1733 | int timeout = 0; |
1692 | __u16 count; | 1734 | __u16 count; |
@@ -1697,8 +1739,6 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, | |||
1697 | if (rc) | 1739 | if (rc) |
1698 | return rc; | 1740 | return rc; |
1699 | 1741 | ||
1700 | pSMBr = (LOCK_RSP *)pSMB; /* BB removeme BB */ | ||
1701 | |||
1702 | if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) { | 1742 | if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) { |
1703 | timeout = CIFS_ASYNC_OP; /* no response expected */ | 1743 | timeout = CIFS_ASYNC_OP; /* no response expected */ |
1704 | pSMB->Timeout = 0; | 1744 | pSMB->Timeout = 0; |
@@ -1732,7 +1772,7 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, | |||
1732 | 1772 | ||
1733 | if (waitFlag) { | 1773 | if (waitFlag) { |
1734 | rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB, | 1774 | rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB, |
1735 | (struct smb_hdr *) pSMBr, &bytes_returned); | 1775 | (struct smb_hdr *) pSMB, &bytes_returned); |
1736 | cifs_small_buf_release(pSMB); | 1776 | cifs_small_buf_release(pSMB); |
1737 | } else { | 1777 | } else { |
1738 | rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *)pSMB, | 1778 | rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *)pSMB, |
@@ -1767,7 +1807,7 @@ CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon, | |||
1767 | cFYI(1, ("Posix Lock")); | 1807 | cFYI(1, ("Posix Lock")); |
1768 | 1808 | ||
1769 | if (pLockData == NULL) | 1809 | if (pLockData == NULL) |
1770 | return EINVAL; | 1810 | return -EINVAL; |
1771 | 1811 | ||
1772 | rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB); | 1812 | rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB); |
1773 | 1813 | ||
@@ -1944,7 +1984,7 @@ renameRetry: | |||
1944 | /* protocol requires ASCII signature byte on Unicode string */ | 1984 | /* protocol requires ASCII signature byte on Unicode string */ |
1945 | pSMB->OldFileName[name_len + 1] = 0x00; | 1985 | pSMB->OldFileName[name_len + 1] = 0x00; |
1946 | name_len2 = | 1986 | name_len2 = |
1947 | cifsConvertToUCS((__le16 *) &pSMB->OldFileName[name_len + 2], | 1987 | cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2], |
1948 | toName, PATH_MAX, nls_codepage, remap); | 1988 | toName, PATH_MAX, nls_codepage, remap); |
1949 | name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ; | 1989 | name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ; |
1950 | name_len2 *= 2; /* convert to bytes */ | 1990 | name_len2 *= 2; /* convert to bytes */ |
@@ -2117,8 +2157,7 @@ copyRetry: | |||
2117 | cFYI(1, ("Send error in copy = %d with %d files copied", | 2157 | cFYI(1, ("Send error in copy = %d with %d files copied", |
2118 | rc, le16_to_cpu(pSMBr->CopyCount))); | 2158 | rc, le16_to_cpu(pSMBr->CopyCount))); |
2119 | } | 2159 | } |
2120 | if (pSMB) | 2160 | cifs_buf_release(pSMB); |
2121 | cifs_buf_release(pSMB); | ||
2122 | 2161 | ||
2123 | if (rc == -EAGAIN) | 2162 | if (rc == -EAGAIN) |
2124 | goto copyRetry; | 2163 | goto copyRetry; |
@@ -2207,8 +2246,7 @@ createSymLinkRetry: | |||
2207 | if (rc) | 2246 | if (rc) |
2208 | cFYI(1, ("Send error in SetPathInfo create symlink = %d", rc)); | 2247 | cFYI(1, ("Send error in SetPathInfo create symlink = %d", rc)); |
2209 | 2248 | ||
2210 | if (pSMB) | 2249 | cifs_buf_release(pSMB); |
2211 | cifs_buf_release(pSMB); | ||
2212 | 2250 | ||
2213 | if (rc == -EAGAIN) | 2251 | if (rc == -EAGAIN) |
2214 | goto createSymLinkRetry; | 2252 | goto createSymLinkRetry; |
@@ -2925,7 +2963,8 @@ setAclRetry: | |||
2925 | } | 2963 | } |
2926 | params = 6 + name_len; | 2964 | params = 6 + name_len; |
2927 | pSMB->MaxParameterCount = cpu_to_le16(2); | 2965 | pSMB->MaxParameterCount = cpu_to_le16(2); |
2928 | pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */ | 2966 | /* BB find max SMB size from sess */ |
2967 | pSMB->MaxDataCount = cpu_to_le16(1000); | ||
2929 | pSMB->MaxSetupCount = 0; | 2968 | pSMB->MaxSetupCount = 0; |
2930 | pSMB->Reserved = 0; | 2969 | pSMB->Reserved = 0; |
2931 | pSMB->Flags = 0; | 2970 | pSMB->Flags = 0; |
@@ -3322,7 +3361,8 @@ QPathInfoRetry: | |||
3322 | params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */; | 3361 | params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */; |
3323 | pSMB->TotalDataCount = 0; | 3362 | pSMB->TotalDataCount = 0; |
3324 | pSMB->MaxParameterCount = cpu_to_le16(2); | 3363 | pSMB->MaxParameterCount = cpu_to_le16(2); |
3325 | pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */ | 3364 | /* BB find exact max SMB PDU from sess structure BB */ |
3365 | pSMB->MaxDataCount = cpu_to_le16(4000); | ||
3326 | pSMB->MaxSetupCount = 0; | 3366 | pSMB->MaxSetupCount = 0; |
3327 | pSMB->Reserved = 0; | 3367 | pSMB->Reserved = 0; |
3328 | pSMB->Flags = 0; | 3368 | pSMB->Flags = 0; |
@@ -3388,7 +3428,7 @@ QPathInfoRetry: | |||
3388 | int | 3428 | int |
3389 | CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon, | 3429 | CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon, |
3390 | const unsigned char *searchName, | 3430 | const unsigned char *searchName, |
3391 | FILE_UNIX_BASIC_INFO * pFindData, | 3431 | FILE_UNIX_BASIC_INFO *pFindData, |
3392 | const struct nls_table *nls_codepage, int remap) | 3432 | const struct nls_table *nls_codepage, int remap) |
3393 | { | 3433 | { |
3394 | /* SMB_QUERY_FILE_UNIX_BASIC */ | 3434 | /* SMB_QUERY_FILE_UNIX_BASIC */ |
@@ -3679,6 +3719,7 @@ int CIFSFindNext(const int xid, struct cifsTconInfo *tcon, | |||
3679 | if (rc) { | 3719 | if (rc) { |
3680 | if (rc == -EBADF) { | 3720 | if (rc == -EBADF) { |
3681 | psrch_inf->endOfSearch = true; | 3721 | psrch_inf->endOfSearch = true; |
3722 | cifs_buf_release(pSMB); | ||
3682 | rc = 0; /* search probably was closed at end of search*/ | 3723 | rc = 0; /* search probably was closed at end of search*/ |
3683 | } else | 3724 | } else |
3684 | cFYI(1, ("FindNext returned = %d", rc)); | 3725 | cFYI(1, ("FindNext returned = %d", rc)); |
@@ -3856,25 +3897,112 @@ GetInodeNumOut: | |||
3856 | return rc; | 3897 | return rc; |
3857 | } | 3898 | } |
3858 | 3899 | ||
3900 | /* parses DFS refferal V3 structure | ||
3901 | * caller is responsible for freeing target_nodes | ||
3902 | * returns: | ||
3903 | * on success - 0 | ||
3904 | * on failure - errno | ||
3905 | */ | ||
3906 | static int | ||
3907 | parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr, | ||
3908 | unsigned int *num_of_nodes, | ||
3909 | struct dfs_info3_param **target_nodes, | ||
3910 | const struct nls_table *nls_codepage) | ||
3911 | { | ||
3912 | int i, rc = 0; | ||
3913 | char *data_end; | ||
3914 | bool is_unicode; | ||
3915 | struct dfs_referral_level_3 *ref; | ||
3916 | |||
3917 | is_unicode = pSMBr->hdr.Flags2 & SMBFLG2_UNICODE; | ||
3918 | *num_of_nodes = le16_to_cpu(pSMBr->NumberOfReferrals); | ||
3919 | |||
3920 | if (*num_of_nodes < 1) { | ||
3921 | cERROR(1, ("num_referrals: must be at least > 0," | ||
3922 | "but we get num_referrals = %d\n", *num_of_nodes)); | ||
3923 | rc = -EINVAL; | ||
3924 | goto parse_DFS_referrals_exit; | ||
3925 | } | ||
3926 | |||
3927 | ref = (struct dfs_referral_level_3 *) &(pSMBr->referrals); | ||
3928 | if (ref->VersionNumber != cpu_to_le16(3)) { | ||
3929 | cERROR(1, ("Referrals of V%d version are not supported," | ||
3930 | "should be V3", le16_to_cpu(ref->VersionNumber))); | ||
3931 | rc = -EINVAL; | ||
3932 | goto parse_DFS_referrals_exit; | ||
3933 | } | ||
3934 | |||
3935 | /* get the upper boundary of the resp buffer */ | ||
3936 | data_end = (char *)(&(pSMBr->PathConsumed)) + | ||
3937 | le16_to_cpu(pSMBr->t2.DataCount); | ||
3938 | |||
3939 | cFYI(1, ("num_referrals: %d dfs flags: 0x%x ... \n", | ||
3940 | *num_of_nodes, | ||
3941 | le16_to_cpu(pSMBr->DFSFlags))); | ||
3942 | |||
3943 | *target_nodes = kzalloc(sizeof(struct dfs_info3_param) * | ||
3944 | *num_of_nodes, GFP_KERNEL); | ||
3945 | if (*target_nodes == NULL) { | ||
3946 | cERROR(1, ("Failed to allocate buffer for target_nodes\n")); | ||
3947 | rc = -ENOMEM; | ||
3948 | goto parse_DFS_referrals_exit; | ||
3949 | } | ||
3950 | |||
3951 | /* collect neccessary data from referrals */ | ||
3952 | for (i = 0; i < *num_of_nodes; i++) { | ||
3953 | char *temp; | ||
3954 | int max_len; | ||
3955 | struct dfs_info3_param *node = (*target_nodes)+i; | ||
3956 | |||
3957 | node->flags = le16_to_cpu(pSMBr->DFSFlags); | ||
3958 | node->path_consumed = le16_to_cpu(pSMBr->PathConsumed); | ||
3959 | node->server_type = le16_to_cpu(ref->ServerType); | ||
3960 | node->ref_flag = le16_to_cpu(ref->ReferralEntryFlags); | ||
3961 | |||
3962 | /* copy DfsPath */ | ||
3963 | temp = (char *)ref + le16_to_cpu(ref->DfsPathOffset); | ||
3964 | max_len = data_end - temp; | ||
3965 | rc = cifs_strncpy_to_host(&(node->path_name), temp, | ||
3966 | max_len, is_unicode, nls_codepage); | ||
3967 | if (rc) | ||
3968 | goto parse_DFS_referrals_exit; | ||
3969 | |||
3970 | /* copy link target UNC */ | ||
3971 | temp = (char *)ref + le16_to_cpu(ref->NetworkAddressOffset); | ||
3972 | max_len = data_end - temp; | ||
3973 | rc = cifs_strncpy_to_host(&(node->node_name), temp, | ||
3974 | max_len, is_unicode, nls_codepage); | ||
3975 | if (rc) | ||
3976 | goto parse_DFS_referrals_exit; | ||
3977 | |||
3978 | ref += le16_to_cpu(ref->Size); | ||
3979 | } | ||
3980 | |||
3981 | parse_DFS_referrals_exit: | ||
3982 | if (rc) { | ||
3983 | free_dfs_info_array(*target_nodes, *num_of_nodes); | ||
3984 | *target_nodes = NULL; | ||
3985 | *num_of_nodes = 0; | ||
3986 | } | ||
3987 | return rc; | ||
3988 | } | ||
3989 | |||
3859 | int | 3990 | int |
3860 | CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses, | 3991 | CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses, |
3861 | const unsigned char *searchName, | 3992 | const unsigned char *searchName, |
3862 | unsigned char **targetUNCs, | 3993 | struct dfs_info3_param **target_nodes, |
3863 | unsigned int *number_of_UNC_in_array, | 3994 | unsigned int *num_of_nodes, |
3864 | const struct nls_table *nls_codepage, int remap) | 3995 | const struct nls_table *nls_codepage, int remap) |
3865 | { | 3996 | { |
3866 | /* TRANS2_GET_DFS_REFERRAL */ | 3997 | /* TRANS2_GET_DFS_REFERRAL */ |
3867 | TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL; | 3998 | TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL; |
3868 | TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL; | 3999 | TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL; |
3869 | struct dfs_referral_level_3 *referrals = NULL; | ||
3870 | int rc = 0; | 4000 | int rc = 0; |
3871 | int bytes_returned; | 4001 | int bytes_returned; |
3872 | int name_len; | 4002 | int name_len; |
3873 | unsigned int i; | ||
3874 | char *temp; | ||
3875 | __u16 params, byte_count; | 4003 | __u16 params, byte_count; |
3876 | *number_of_UNC_in_array = 0; | 4004 | *num_of_nodes = 0; |
3877 | *targetUNCs = NULL; | 4005 | *target_nodes = NULL; |
3878 | 4006 | ||
3879 | cFYI(1, ("In GetDFSRefer the path %s", searchName)); | 4007 | cFYI(1, ("In GetDFSRefer the path %s", searchName)); |
3880 | if (ses == NULL) | 4008 | if (ses == NULL) |
@@ -3921,7 +4049,8 @@ getDFSRetry: | |||
3921 | pSMB->DataCount = 0; | 4049 | pSMB->DataCount = 0; |
3922 | pSMB->DataOffset = 0; | 4050 | pSMB->DataOffset = 0; |
3923 | pSMB->MaxParameterCount = 0; | 4051 | pSMB->MaxParameterCount = 0; |
3924 | pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */ | 4052 | /* BB find exact max SMB PDU from sess structure BB */ |
4053 | pSMB->MaxDataCount = cpu_to_le16(4000); | ||
3925 | pSMB->MaxSetupCount = 0; | 4054 | pSMB->MaxSetupCount = 0; |
3926 | pSMB->Reserved = 0; | 4055 | pSMB->Reserved = 0; |
3927 | pSMB->Flags = 0; | 4056 | pSMB->Flags = 0; |
@@ -3943,103 +4072,26 @@ getDFSRetry: | |||
3943 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 4072 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
3944 | if (rc) { | 4073 | if (rc) { |
3945 | cFYI(1, ("Send error in GetDFSRefer = %d", rc)); | 4074 | cFYI(1, ("Send error in GetDFSRefer = %d", rc)); |
3946 | } else { /* decode response */ | 4075 | goto GetDFSRefExit; |
3947 | /* BB Add logic to parse referrals here */ | 4076 | } |
3948 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); | 4077 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); |
3949 | 4078 | ||
3950 | /* BB Also check if enough total bytes returned? */ | 4079 | /* BB Also check if enough total bytes returned? */ |
3951 | if (rc || (pSMBr->ByteCount < 17)) | 4080 | if (rc || (pSMBr->ByteCount < 17)) { |
3952 | rc = -EIO; /* bad smb */ | 4081 | rc = -EIO; /* bad smb */ |
3953 | else { | 4082 | goto GetDFSRefExit; |
3954 | __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); | 4083 | } |
3955 | __u16 data_count = le16_to_cpu(pSMBr->t2.DataCount); | ||
3956 | 4084 | ||
3957 | cFYI(1, | 4085 | cFYI(1, ("Decoding GetDFSRefer response BCC: %d Offset %d", |
3958 | ("Decoding GetDFSRefer response BCC: %d Offset %d", | 4086 | pSMBr->ByteCount, |
3959 | pSMBr->ByteCount, data_offset)); | 4087 | le16_to_cpu(pSMBr->t2.DataOffset))); |
3960 | referrals = | ||
3961 | (struct dfs_referral_level_3 *) | ||
3962 | (8 /* sizeof start of data block */ + | ||
3963 | data_offset + | ||
3964 | (char *) &pSMBr->hdr.Protocol); | ||
3965 | cFYI(1, ("num_referrals: %d dfs flags: 0x%x ... \n" | ||
3966 | "for referral one refer size: 0x%x srv " | ||
3967 | "type: 0x%x refer flags: 0x%x ttl: 0x%x", | ||
3968 | le16_to_cpu(pSMBr->NumberOfReferrals), | ||
3969 | le16_to_cpu(pSMBr->DFSFlags), | ||
3970 | le16_to_cpu(referrals->ReferralSize), | ||
3971 | le16_to_cpu(referrals->ServerType), | ||
3972 | le16_to_cpu(referrals->ReferralFlags), | ||
3973 | le16_to_cpu(referrals->TimeToLive))); | ||
3974 | /* BB This field is actually two bytes in from start of | ||
3975 | data block so we could do safety check that DataBlock | ||
3976 | begins at address of pSMBr->NumberOfReferrals */ | ||
3977 | *number_of_UNC_in_array = | ||
3978 | le16_to_cpu(pSMBr->NumberOfReferrals); | ||
3979 | |||
3980 | /* BB Fix below so can return more than one referral */ | ||
3981 | if (*number_of_UNC_in_array > 1) | ||
3982 | *number_of_UNC_in_array = 1; | ||
3983 | |||
3984 | /* get the length of the strings describing refs */ | ||
3985 | name_len = 0; | ||
3986 | for (i = 0; i < *number_of_UNC_in_array; i++) { | ||
3987 | /* make sure that DfsPathOffset not past end */ | ||
3988 | __u16 offset = | ||
3989 | le16_to_cpu(referrals->DfsPathOffset); | ||
3990 | if (offset > data_count) { | ||
3991 | /* if invalid referral, stop here and do | ||
3992 | not try to copy any more */ | ||
3993 | *number_of_UNC_in_array = i; | ||
3994 | break; | ||
3995 | } | ||
3996 | temp = ((char *)referrals) + offset; | ||
3997 | 4088 | ||
3998 | if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) { | 4089 | /* parse returned result into more usable form */ |
3999 | name_len += UniStrnlen((wchar_t *)temp, | 4090 | rc = parse_DFS_referrals(pSMBr, num_of_nodes, |
4000 | data_count); | 4091 | target_nodes, nls_codepage); |
4001 | } else { | ||
4002 | name_len += strnlen(temp, data_count); | ||
4003 | } | ||
4004 | referrals++; | ||
4005 | /* BB add check that referral pointer does | ||
4006 | not fall off end PDU */ | ||
4007 | } | ||
4008 | /* BB add check for name_len bigger than bcc */ | ||
4009 | *targetUNCs = | ||
4010 | kmalloc(name_len+1+(*number_of_UNC_in_array), | ||
4011 | GFP_KERNEL); | ||
4012 | if (*targetUNCs == NULL) { | ||
4013 | rc = -ENOMEM; | ||
4014 | goto GetDFSRefExit; | ||
4015 | } | ||
4016 | /* copy the ref strings */ | ||
4017 | referrals = (struct dfs_referral_level_3 *) | ||
4018 | (8 /* sizeof data hdr */ + data_offset + | ||
4019 | (char *) &pSMBr->hdr.Protocol); | ||
4020 | |||
4021 | for (i = 0; i < *number_of_UNC_in_array; i++) { | ||
4022 | temp = ((char *)referrals) + | ||
4023 | le16_to_cpu(referrals->DfsPathOffset); | ||
4024 | if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) { | ||
4025 | cifs_strfromUCS_le(*targetUNCs, | ||
4026 | (__le16 *) temp, | ||
4027 | name_len, | ||
4028 | nls_codepage); | ||
4029 | } else { | ||
4030 | strncpy(*targetUNCs, temp, name_len); | ||
4031 | } | ||
4032 | /* BB update target_uncs pointers */ | ||
4033 | referrals++; | ||
4034 | } | ||
4035 | temp = *targetUNCs; | ||
4036 | temp[name_len] = 0; | ||
4037 | } | ||
4038 | 4092 | ||
4039 | } | ||
4040 | GetDFSRefExit: | 4093 | GetDFSRefExit: |
4041 | if (pSMB) | 4094 | cifs_buf_release(pSMB); |
4042 | cifs_buf_release(pSMB); | ||
4043 | 4095 | ||
4044 | if (rc == -EAGAIN) | 4096 | if (rc == -EAGAIN) |
4045 | goto getDFSRetry; | 4097 | goto getDFSRetry; |
@@ -4229,7 +4281,8 @@ QFSAttributeRetry: | |||
4229 | params = 2; /* level */ | 4281 | params = 2; /* level */ |
4230 | pSMB->TotalDataCount = 0; | 4282 | pSMB->TotalDataCount = 0; |
4231 | pSMB->MaxParameterCount = cpu_to_le16(2); | 4283 | pSMB->MaxParameterCount = cpu_to_le16(2); |
4232 | pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */ | 4284 | /* BB find exact max SMB PDU from sess structure BB */ |
4285 | pSMB->MaxDataCount = cpu_to_le16(1000); | ||
4233 | pSMB->MaxSetupCount = 0; | 4286 | pSMB->MaxSetupCount = 0; |
4234 | pSMB->Reserved = 0; | 4287 | pSMB->Reserved = 0; |
4235 | pSMB->Flags = 0; | 4288 | pSMB->Flags = 0; |
@@ -4298,7 +4351,8 @@ QFSDeviceRetry: | |||
4298 | params = 2; /* level */ | 4351 | params = 2; /* level */ |
4299 | pSMB->TotalDataCount = 0; | 4352 | pSMB->TotalDataCount = 0; |
4300 | pSMB->MaxParameterCount = cpu_to_le16(2); | 4353 | pSMB->MaxParameterCount = cpu_to_le16(2); |
4301 | pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */ | 4354 | /* BB find exact max SMB PDU from sess structure BB */ |
4355 | pSMB->MaxDataCount = cpu_to_le16(1000); | ||
4302 | pSMB->MaxSetupCount = 0; | 4356 | pSMB->MaxSetupCount = 0; |
4303 | pSMB->Reserved = 0; | 4357 | pSMB->Reserved = 0; |
4304 | pSMB->Flags = 0; | 4358 | pSMB->Flags = 0; |
@@ -4369,7 +4423,8 @@ QFSUnixRetry: | |||
4369 | pSMB->DataCount = 0; | 4423 | pSMB->DataCount = 0; |
4370 | pSMB->DataOffset = 0; | 4424 | pSMB->DataOffset = 0; |
4371 | pSMB->MaxParameterCount = cpu_to_le16(2); | 4425 | pSMB->MaxParameterCount = cpu_to_le16(2); |
4372 | pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */ | 4426 | /* BB find exact max SMB PDU from sess structure BB */ |
4427 | pSMB->MaxDataCount = cpu_to_le16(100); | ||
4373 | pSMB->MaxSetupCount = 0; | 4428 | pSMB->MaxSetupCount = 0; |
4374 | pSMB->Reserved = 0; | 4429 | pSMB->Reserved = 0; |
4375 | pSMB->Flags = 0; | 4430 | pSMB->Flags = 0; |
@@ -4444,7 +4499,8 @@ SETFSUnixRetry: | |||
4444 | offset = param_offset + params; | 4499 | offset = param_offset + params; |
4445 | 4500 | ||
4446 | pSMB->MaxParameterCount = cpu_to_le16(4); | 4501 | pSMB->MaxParameterCount = cpu_to_le16(4); |
4447 | pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */ | 4502 | /* BB find exact max SMB PDU from sess structure BB */ |
4503 | pSMB->MaxDataCount = cpu_to_le16(100); | ||
4448 | pSMB->SetupCount = 1; | 4504 | pSMB->SetupCount = 1; |
4449 | pSMB->Reserved3 = 0; | 4505 | pSMB->Reserved3 = 0; |
4450 | pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION); | 4506 | pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION); |
@@ -4512,7 +4568,8 @@ QFSPosixRetry: | |||
4512 | pSMB->DataCount = 0; | 4568 | pSMB->DataCount = 0; |
4513 | pSMB->DataOffset = 0; | 4569 | pSMB->DataOffset = 0; |
4514 | pSMB->MaxParameterCount = cpu_to_le16(2); | 4570 | pSMB->MaxParameterCount = cpu_to_le16(2); |
4515 | pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */ | 4571 | /* BB find exact max SMB PDU from sess structure BB */ |
4572 | pSMB->MaxDataCount = cpu_to_le16(100); | ||
4516 | pSMB->MaxSetupCount = 0; | 4573 | pSMB->MaxSetupCount = 0; |
4517 | pSMB->Reserved = 0; | 4574 | pSMB->Reserved = 0; |
4518 | pSMB->Flags = 0; | 4575 | pSMB->Flags = 0; |
@@ -4702,7 +4759,8 @@ CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size, | |||
4702 | 4759 | ||
4703 | count = sizeof(struct file_end_of_file_info); | 4760 | count = sizeof(struct file_end_of_file_info); |
4704 | pSMB->MaxParameterCount = cpu_to_le16(2); | 4761 | pSMB->MaxParameterCount = cpu_to_le16(2); |
4705 | pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */ | 4762 | /* BB find exact max SMB PDU from sess structure BB */ |
4763 | pSMB->MaxDataCount = cpu_to_le16(1000); | ||
4706 | pSMB->SetupCount = 1; | 4764 | pSMB->SetupCount = 1; |
4707 | pSMB->Reserved3 = 0; | 4765 | pSMB->Reserved3 = 0; |
4708 | pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION); | 4766 | pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION); |
@@ -4789,7 +4847,8 @@ CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon, | |||
4789 | 4847 | ||
4790 | count = sizeof(FILE_BASIC_INFO); | 4848 | count = sizeof(FILE_BASIC_INFO); |
4791 | pSMB->MaxParameterCount = cpu_to_le16(2); | 4849 | pSMB->MaxParameterCount = cpu_to_le16(2); |
4792 | pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */ | 4850 | /* BB find max SMB PDU from sess */ |
4851 | pSMB->MaxDataCount = cpu_to_le16(1000); | ||
4793 | pSMB->SetupCount = 1; | 4852 | pSMB->SetupCount = 1; |
4794 | pSMB->Reserved3 = 0; | 4853 | pSMB->Reserved3 = 0; |
4795 | pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION); | 4854 | pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION); |
@@ -4856,7 +4915,8 @@ SetTimesRetry: | |||
4856 | params = 6 + name_len; | 4915 | params = 6 + name_len; |
4857 | count = sizeof(FILE_BASIC_INFO); | 4916 | count = sizeof(FILE_BASIC_INFO); |
4858 | pSMB->MaxParameterCount = cpu_to_le16(2); | 4917 | pSMB->MaxParameterCount = cpu_to_le16(2); |
4859 | pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */ | 4918 | /* BB find max SMB PDU from sess structure BB */ |
4919 | pSMB->MaxDataCount = cpu_to_le16(1000); | ||
4860 | pSMB->MaxSetupCount = 0; | 4920 | pSMB->MaxSetupCount = 0; |
4861 | pSMB->Reserved = 0; | 4921 | pSMB->Reserved = 0; |
4862 | pSMB->Flags = 0; | 4922 | pSMB->Flags = 0; |
@@ -4986,7 +5046,8 @@ setPermsRetry: | |||
4986 | params = 6 + name_len; | 5046 | params = 6 + name_len; |
4987 | count = sizeof(FILE_UNIX_BASIC_INFO); | 5047 | count = sizeof(FILE_UNIX_BASIC_INFO); |
4988 | pSMB->MaxParameterCount = cpu_to_le16(2); | 5048 | pSMB->MaxParameterCount = cpu_to_le16(2); |
4989 | pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */ | 5049 | /* BB find max SMB PDU from sess structure BB */ |
5050 | pSMB->MaxDataCount = cpu_to_le16(1000); | ||
4990 | pSMB->MaxSetupCount = 0; | 5051 | pSMB->MaxSetupCount = 0; |
4991 | pSMB->Reserved = 0; | 5052 | pSMB->Reserved = 0; |
4992 | pSMB->Flags = 0; | 5053 | pSMB->Flags = 0; |
@@ -5051,8 +5112,7 @@ setPermsRetry: | |||
5051 | if (rc) | 5112 | if (rc) |
5052 | cFYI(1, ("SetPathInfo (perms) returned %d", rc)); | 5113 | cFYI(1, ("SetPathInfo (perms) returned %d", rc)); |
5053 | 5114 | ||
5054 | if (pSMB) | 5115 | cifs_buf_release(pSMB); |
5055 | cifs_buf_release(pSMB); | ||
5056 | if (rc == -EAGAIN) | 5116 | if (rc == -EAGAIN) |
5057 | goto setPermsRetry; | 5117 | goto setPermsRetry; |
5058 | return rc; | 5118 | return rc; |
@@ -5169,7 +5229,8 @@ QAllEAsRetry: | |||
5169 | params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */; | 5229 | params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */; |
5170 | pSMB->TotalDataCount = 0; | 5230 | pSMB->TotalDataCount = 0; |
5171 | pSMB->MaxParameterCount = cpu_to_le16(2); | 5231 | pSMB->MaxParameterCount = cpu_to_le16(2); |
5172 | pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */ | 5232 | /* BB find exact max SMB PDU from sess structure BB */ |
5233 | pSMB->MaxDataCount = cpu_to_le16(4000); | ||
5173 | pSMB->MaxSetupCount = 0; | 5234 | pSMB->MaxSetupCount = 0; |
5174 | pSMB->Reserved = 0; | 5235 | pSMB->Reserved = 0; |
5175 | pSMB->Flags = 0; | 5236 | pSMB->Flags = 0; |
@@ -5273,8 +5334,7 @@ QAllEAsRetry: | |||
5273 | } | 5334 | } |
5274 | } | 5335 | } |
5275 | } | 5336 | } |
5276 | if (pSMB) | 5337 | cifs_buf_release(pSMB); |
5277 | cifs_buf_release(pSMB); | ||
5278 | if (rc == -EAGAIN) | 5338 | if (rc == -EAGAIN) |
5279 | goto QAllEAsRetry; | 5339 | goto QAllEAsRetry; |
5280 | 5340 | ||
@@ -5317,7 +5377,8 @@ QEARetry: | |||
5317 | params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */; | 5377 | params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */; |
5318 | pSMB->TotalDataCount = 0; | 5378 | pSMB->TotalDataCount = 0; |
5319 | pSMB->MaxParameterCount = cpu_to_le16(2); | 5379 | pSMB->MaxParameterCount = cpu_to_le16(2); |
5320 | pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */ | 5380 | /* BB find exact max SMB PDU from sess structure BB */ |
5381 | pSMB->MaxDataCount = cpu_to_le16(4000); | ||
5321 | pSMB->MaxSetupCount = 0; | 5382 | pSMB->MaxSetupCount = 0; |
5322 | pSMB->Reserved = 0; | 5383 | pSMB->Reserved = 0; |
5323 | pSMB->Flags = 0; | 5384 | pSMB->Flags = 0; |
@@ -5422,8 +5483,7 @@ QEARetry: | |||
5422 | } | 5483 | } |
5423 | } | 5484 | } |
5424 | } | 5485 | } |
5425 | if (pSMB) | 5486 | cifs_buf_release(pSMB); |
5426 | cifs_buf_release(pSMB); | ||
5427 | if (rc == -EAGAIN) | 5487 | if (rc == -EAGAIN) |
5428 | goto QEARetry; | 5488 | goto QEARetry; |
5429 | 5489 | ||
@@ -5475,7 +5535,8 @@ SetEARetry: | |||
5475 | 5535 | ||
5476 | count = sizeof(*parm_data) + ea_value_len + name_len; | 5536 | count = sizeof(*parm_data) + ea_value_len + name_len; |
5477 | pSMB->MaxParameterCount = cpu_to_le16(2); | 5537 | pSMB->MaxParameterCount = cpu_to_le16(2); |
5478 | pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */ | 5538 | /* BB find max SMB PDU from sess */ |
5539 | pSMB->MaxDataCount = cpu_to_le16(1000); | ||
5479 | pSMB->MaxSetupCount = 0; | 5540 | pSMB->MaxSetupCount = 0; |
5480 | pSMB->Reserved = 0; | 5541 | pSMB->Reserved = 0; |
5481 | pSMB->Flags = 0; | 5542 | pSMB->Flags = 0; |