/// <summary> /// Verify members in Error_Context /// </summary> /// <param name="ctx">Error_Context in Error Response</param> /// <param name="uncSharePath">uncSharePath</param> /// <param name="sofsHostedNode">ScaleOutFS hosted node</param> private void verifyErrorContext(Error_Context ctx, string uncSharePath, string sofsHostedNode) { #region Verify Error_Context BaseTestSite.Assert.AreEqual( Error_Id.ERROR_ID_SHARE_REDIRECT, ctx.ErrorId, "The Error ID should be SMB2_ERROR_ID_SHARE_REDIRECT, actually server returns {0}", ctx.ErrorId); BaseTestSite.Assert.IsTrue( ctx.ErrorDataLength > 0, "The length, in bytes, of the ErrorContextData field should be greater than 0. Actually server returns {0}.", ctx.ErrorDataLength); #endregion #region Verify Share_Reditect_Error_Context_Response Share_Redirect_Error_Context_Response errCtx = ctx.ErrorData.ShareRedirectErrorContextResponse; BaseTestSite.Assert.IsTrue( errCtx.StructureSize > 0, "This field (StructureSize) MUST be set to the size of the structure. Actually server returns {0}.", errCtx.StructureSize); BaseTestSite.Assert.AreEqual( (uint)3, errCtx.NotificationType, "This field (NotificationType) MUST be set to 3. Actually server returns {0}.", errCtx.NotificationType); byte[] uncSharePathToByte = Encoding.Unicode.GetBytes(uncSharePath); BaseTestSite.Assert.AreEqual( (uint)uncSharePathToByte.Length, errCtx.ResourceNameLength, "The length of the share name provided in the ResourceName field, in bytes, should be the length of {0}. Actually server returns {1}.", uncSharePathToByte.Length, errCtx.ResourceNameLength); BaseTestSite.Assert.AreEqual( 0, errCtx.Flags, "This field (Flags) MUST be set to zero. Actually server returns {0}.", errCtx.Flags); BaseTestSite.Assert.AreEqual( 0, errCtx.TargetType, "This field (TargetType) MUST be set to zero. Actually server returns {0}.", errCtx.TargetType); BaseTestSite.Assert.IsTrue( errCtx.IPAddrCount > 0, "The number of MOVE_DST_IPADDR structures in the IPAddrMoveList field should be greater than 0. Actually server returns {0}.", errCtx.IPAddrCount); IPAddress[] ipv4AddressList = Dns.GetHostEntry(sofsHostedNode).AddressList; System.Net.Sockets.AddressFamily addressFamily = ipv4AddressList[0].AddressFamily; for (int i = 0; i < errCtx.IPAddrCount; i++) { Move_Dst_IpAddr dstMoveIpAddr = errCtx.IPAddrMoveList[i]; BaseTestSite.Assert.AreEqual( (uint)0, dstMoveIpAddr.Reserved, "The server SHOULD set this field to zero, and the client MUST ignore it on receipt. Actually server returns {0}", dstMoveIpAddr.Reserved); if (addressFamily == System.Net.Sockets.AddressFamily.InterNetwork) { BaseTestSite.Assert.AreEqual( Move_Dst_IpAddr_Type.MOVE_DST_IPADDR_V4, dstMoveIpAddr.Type, "Type of destination IP address should be MOVE_DST_IPADDR_V4, actually server returns {0}", dstMoveIpAddr.Type); // Check Reserved2 field (offset from 4 to 15) is 0 for (int k = 4; k < 16; k++) { BaseTestSite.Assert.IsTrue( dstMoveIpAddr.IPv6Address[k] == 0, "The client MUST set this (Reserved2) to 0."); } } else if (addressFamily == System.Net.Sockets.AddressFamily.InterNetworkV6) { BaseTestSite.Assert.AreEqual( Move_Dst_IpAddr_Type.MOVE_DST_IPADDR_V6, dstMoveIpAddr.Type, "Type of destination IP address should be MOVE_DST_IPADDR_V6, actually server returns {0}", dstMoveIpAddr.Type); } } // Verify all IP addresses for this node are in IPAddrMoveList if (addressFamily == System.Net.Sockets.AddressFamily.InterNetwork) { for (int i = 0; i < ipv4AddressList.Length; i++) { IPAddress curAddr = ipv4AddressList[i]; bool isIpAddrInList = false; for (int j = 0; j < errCtx.IPAddrMoveList.Length; j++) { Move_Dst_IpAddr dstMoveIpAddr = errCtx.IPAddrMoveList[j]; uint ipAddr = BitConverter.ToUInt32(dstMoveIpAddr.IPv6Address, 0); if (ipAddr == (uint)curAddr.Address) { isIpAddrInList = true; break; } } BaseTestSite.Assert.IsTrue(isIpAddrInList, "IP address of sofsHostedNode {0} is not in IPAddrMoveList.", curAddr.ToString()); } } string resourceName = Encoding.Unicode.GetString(errCtx.ResourceName, 0, (int)errCtx.ResourceNameLength); BaseTestSite.Assert.IsTrue( uncSharePath.ToLower().Contains(resourceName.ToLower()), "ResourceName should be the same as uncSharePath. Actually server returns {0}.", resourceName); #endregion }
/// <summary> /// Verify members in Error_Context /// </summary> /// <param name="ctx">Error_Context in Error Response</param> /// <param name="uncSharePath">uncSharePath</param> /// <param name="sofsHostedNode">ScaleOutFS hosted node</param> private void verifyErrorContext(Error_Context ctx, string uncSharePath, string sofsHostedNode) { #region Verify Error_Context BaseTestSite.Assert.AreEqual( Error_Id.ERROR_ID_SHARE_REDIRECT, ctx.ErrorId, "The Error ID should be SMB2_ERROR_ID_SHARE_REDIRECT, actually server returns {0}", ctx.ErrorId); BaseTestSite.Assert.IsTrue( ctx.ErrorDataLength > 0, "The length, in bytes, of the ErrorContextData field should be greater than 0. Actually server returns {0}.", ctx.ErrorDataLength); #endregion #region Verify Share_Reditect_Error_Context_Response Share_Redirect_Error_Context_Response errCtx = ctx.ErrorData.ShareRedirectErrorContextResponse; BaseTestSite.Assert.IsTrue( errCtx.StructureSize > 0, "This field (StructureSize) MUST be set to the size of the structure. Actually server returns {0}.", errCtx.StructureSize); BaseTestSite.Assert.AreEqual( (uint)3, errCtx.NotificationType, "This field (NotificationType) MUST be set to 3. Actually server returns {0}.", errCtx.NotificationType); BaseTestSite.Assert.AreEqual( 0, errCtx.Flags, "This field (Flags) MUST be set to zero. Actually server returns {0}.", errCtx.Flags); BaseTestSite.Assert.AreEqual( 0, errCtx.TargetType, "This field (TargetType) MUST be set to zero. Actually server returns {0}.", errCtx.TargetType); BaseTestSite.Assert.IsTrue( errCtx.IPAddrCount > 0, "The number of MOVE_DST_IPADDR structures in the IPAddrMoveList field should be greater than 0. Actually server returns {0}.", errCtx.IPAddrCount); IPAddress[] ipv4AddressList = Dns.GetHostAddresses(sofsHostedNode); System.Net.Sockets.AddressFamily addressFamily = ipv4AddressList[0].AddressFamily; for (int i = 0; i < errCtx.IPAddrCount; i++) { Move_Dst_IpAddr dstMoveIpAddr = errCtx.IPAddrMoveList[i]; BaseTestSite.Assert.AreEqual( (uint)0, dstMoveIpAddr.Reserved, "The server SHOULD set this field to zero, and the client MUST ignore it on receipt. Actually server returns {0}", dstMoveIpAddr.Reserved); if (addressFamily == System.Net.Sockets.AddressFamily.InterNetwork) { BaseTestSite.Assert.AreEqual( Move_Dst_IpAddr_Type.MOVE_DST_IPADDR_V4, dstMoveIpAddr.Type, "Type of destination IP address should be MOVE_DST_IPADDR_V4, actually server returns {0}", dstMoveIpAddr.Type); // Check Reserved2 field (offset from 4 to 15) is 0 for (int k = 4; k < 16; k++) { BaseTestSite.Assert.IsTrue( dstMoveIpAddr.IPv6Address[k] == 0, "The client MUST set this (Reserved2) to 0."); } } else if (addressFamily == System.Net.Sockets.AddressFamily.InterNetworkV6) { BaseTestSite.Assert.AreEqual( Move_Dst_IpAddr_Type.MOVE_DST_IPADDR_V6, dstMoveIpAddr.Type, "Type of destination IP address should be MOVE_DST_IPADDR_V6, actually server returns {0}", dstMoveIpAddr.Type); } } // Verify all IP addresses for this node are in IPAddrMoveList if (addressFamily == System.Net.Sockets.AddressFamily.InterNetwork) { for (int i = 0; i < ipv4AddressList.Length; i++) { IPAddress curAddr = ipv4AddressList[i]; bool isIpAddrInList = false; for (int j = 0; j < errCtx.IPAddrMoveList.Length; j++) { Move_Dst_IpAddr dstMoveIpAddr = errCtx.IPAddrMoveList[j]; uint ipAddr = BitConverter.ToUInt32(dstMoveIpAddr.IPv6Address, 0); if (ipAddr == (uint)curAddr.Address) { isIpAddrInList = true; break; } } BaseTestSite.Assert.IsTrue(isIpAddrInList, "IP address of sofsHostedNode {0} is not in IPAddrMoveList.", curAddr.ToString()); } } var resourceName = Encoding.Unicode.GetString(errCtx.ResourceName, 0, (int)errCtx.ResourceNameLength); BaseTestSite.Log.Add(LogEntryKind.Debug, $"uncSharePath: {uncSharePath}"); BaseTestSite.Log.Add(LogEntryKind.Debug, $"ResourceName: {resourceName}"); BaseTestSite.Assert.IsTrue( CompareUNCSharePathAndResourceName(uncSharePath.ToLower(), resourceName.ToLower()), "ResourceName should indicate the same share as what uncSharePath indicates. Actually server returns {0}.", resourceName); bool CompareUNCSharePathAndResourceName(string uncSharePath, string resourceName) { var pathRegex = @"\\\\(?<serverName>.+)\\(?<shareName>.+)"; var regex = new Regex(pathRegex); var uncSharePathMatch = regex.Match(uncSharePath); var shareServer = ExtractServerName(uncSharePathMatch.Groups["serverName"].Value); var shareName = uncSharePathMatch.Groups["shareName"].Value; var resourceNameMatch = regex.Match(resourceName); var resourceShareServer = ExtractServerName(resourceNameMatch.Groups["serverName"].Value); var resourceShareName = resourceNameMatch.Groups["shareName"].Value; return(shareServer == resourceShareServer && shareName == resourceShareName); string ExtractServerName(string matchedGroupValue) { // If the matched value is not an FQDN (e.g. computer name or IP address), return it directly. // If the matched value is an FQDN, extract the server name from it. if (!matchedGroupValue.Contains(TestConfig.DomainName, StringComparison.OrdinalIgnoreCase)) { return(matchedGroupValue); } else { return(matchedGroupValue.Substring(0, matchedGroupValue.IndexOf(TestConfig.DomainName, StringComparison.OrdinalIgnoreCase) - 1)); } } } #endregion }