diff --git a/.gitignore b/.gitignore index fc94d87a4..5db3887f9 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,7 @@ /Distribution/libz.dylib /Distribution/libz.so /Distribution/ZLib.Bindings.dll +/Distribution/Microsoft.Toolkit.HighPerformance.dll /Distribution/runtimes /Distribution/nohup.out /Distribution/ref diff --git a/Projects/Server.Tests/Tests/Network/Packets/Outgoing/AccountPackets.cs b/Projects/Server.Tests/Tests/Network/Packets/Outgoing/AccountPackets.cs index a2f9d6aab..bba17d8af 100644 --- a/Projects/Server.Tests/Tests/Network/Packets/Outgoing/AccountPackets.cs +++ b/Projects/Server.Tests/Tests/Network/Packets/Outgoing/AccountPackets.cs @@ -338,7 +338,8 @@ namespace Server.Tests.Network Stream.WriteAsciiFixed(si.Name, 32); Stream.Write((byte)si.FullPercent); Stream.Write((sbyte)si.TimeZone); - Stream.Write(Utility.GetAddressValue(si.Address.Address)); + // UO Doesn't support IPv6 + Stream.Write(si.RawAddress); } } } @@ -347,7 +348,7 @@ namespace Server.Tests.Network { public PlayServerAck(ServerInfo si, int authId) : base(0x8C, 11) { - var addr = Utility.GetAddressValue(si.Address.Address); + var addr = si.RawAddress; Stream.Write((byte)addr); Stream.Write((byte)(addr >> 8)); diff --git a/Projects/Server.Tests/Tests/Network/PipeTests.cs b/Projects/Server.Tests/Tests/Network/PipeTests.cs index b89c1b1d6..20e2fafe5 100644 --- a/Projects/Server.Tests/Tests/Network/PipeTests.cs +++ b/Projects/Server.Tests/Tests/Network/PipeTests.cs @@ -10,7 +10,7 @@ namespace Server.Tests.Network { private async void DelayedExecute(Action action) { - await Task.Delay(5); + await Task.Delay(5).ConfigureAwait(false); action(); } diff --git a/Projects/Server.Tests/Tests/Utility/HexStringConverterTest.cs b/Projects/Server.Tests/Tests/Utility/HexStringConverterTest.cs index e0eca4301..05d0d9ddd 100644 --- a/Projects/Server.Tests/Tests/Utility/HexStringConverterTest.cs +++ b/Projects/Server.Tests/Tests/Utility/HexStringConverterTest.cs @@ -1,7 +1,7 @@ using System; using Xunit; -namespace Server.Tests.Accounting +namespace Server.Tests { public class HexStringConverterTest { diff --git a/Projects/Server.Tests/Tests/Utility/IPAddressTests.cs b/Projects/Server.Tests/Tests/Utility/IPAddressTests.cs new file mode 100644 index 000000000..2766899ed --- /dev/null +++ b/Projects/Server.Tests/Tests/Utility/IPAddressTests.cs @@ -0,0 +1,78 @@ +using System; +using System.Buffers.Binary; +using System.Collections.Generic; +using System.Net; +using Xunit; + +namespace Server.Tests +{ + public class IPAddressTests + { + [Theory] + [InlineData("192.168.100.254", "192.168.100.1", 16, true)] + [InlineData("192.168.100.254", "192.168.50.1", 24, false)] + [InlineData("192.168.100.1", "192.168.50.1", 32, false)] + [InlineData("192.168.50.1", "192.168.50.1", 32, true)] + [InlineData("192.168.50.4", "192.168.50.7", 30, true)] + [InlineData("192.168.50.4", "192.168.50.9", 30, false)] + [InlineData("::ffff:192.168.100.254", "192.168.100.1", 112, true)] + [InlineData("::ffff:192.168.100.254", "192.168.50.1", 104, true)] + [InlineData("::ffff:192.168.100.254", "192.168.50.1", 120, false)] + [InlineData("1234:5678:9ABC:1234:5678:9ABC:1234:5678", "1234:5677:0:0:0:0:0:0", 16, true)] + [InlineData("1234:5678:9ABC:1234:5678:9ABC:1234:5678", "1234:5677:0:0:0:0:0:0", 64, false)] + [InlineData("::1234:5678", "1234:5677::", 64, false)] + [InlineData("::1234:5678", "::9ABC:5677", 112, false)] + [InlineData("::1234:5678", "::1234:66AA", 112, true)] + [InlineData("::1234:5678", "::1235:FFFF", 109, true)] + [InlineData("::1234:5678", "::1238:ABAC", 109, false)] + public void TestIPvCIDR(string cidr, string addr, int cidrLength, bool shouldMatch) + { + var cidrAddress = IPAddress.Parse(cidr); + var address = IPAddress.Parse(addr); + + Assert.Equal(shouldMatch, Utility.IPMatchCIDR(cidrAddress, address, cidrLength)); + } + + [Theory] + [InlineData("192.168.1.*", "192.168.1.1", true, true)] + [InlineData("192.168.1.100", "192.168.1.1", false, true)] + [InlineData("192.168.*.100", "192.168.1.100", true, true)] + [InlineData("192.168.20-60.100", "192.168.37.100", true, true)] + [InlineData("192.168.20-60.100", "192.168.85.100", false, true)] + [InlineData("192.168.-.100", "192.168.85.100", false, false)] + [InlineData("192.168.x-.100", "192.168.85.100", false, false)] + [InlineData("192.168.x*.100", "192.168.85.100", false, false)] + [InlineData("192.168.**.100", "192.168.85.100", false, false)] + [InlineData("::1234:*", "::1234:5678", true, true)] + [InlineData("::1234-1238:1000", "::1236:1000", true, true)] + [InlineData("::1234-1238:1000", "::1239:1000", false, true)] + [InlineData("::10:*:1234-1238:1000", "::10:55A1:1235:1000", true, true)] + [InlineData("1024:*:1234::", "1024:8A13:1234::", true, true)] + [InlineData("::1024:*:1234::", "1024:8A13:1234::", false, false)] + [InlineData("::1024:*:1234:-", "::1024:8A13:1234", false, false)] + [InlineData("::1024:*1:1234", "::1024:8A13:1234", false, false)] + [InlineData("::1024:*-:1234", "::1024:8A13:1234", false, false)] + [InlineData("::1024:?1:1234", "::1024:8A13:1234", false, false)] + [InlineData("::1024:1_2:1234", "::1024:8A13:1234", false, false)] + public void TestIPMatch(string val, string addr, bool shouldMatch, bool shouldBeValid) + { + var address = IPAddress.Parse(addr); + bool match = Utility.IPMatch(val, address, out var valid); + + Assert.Equal(shouldMatch, match); + Assert.Equal(shouldBeValid, valid); + } + + [Fact] + public void TestMixedIPv4Address() + { + var ip = IPAddress.Parse("::ffff:192.168.1.1"); + var expected = IPAddress.Parse("192.168.1.1"); + + Span integer = stackalloc byte[4]; + expected.TryWriteBytes(integer, out _); + + Assert.Equal(BinaryPrimitives.ReadUInt32BigEndian(integer), Utility.IPv4ToAddress(ip)); + } + } +} diff --git a/Projects/Server/Network/Packets/OutgoingAccountPackets.cs b/Projects/Server/Network/Packets/OutgoingAccountPackets.cs index af923be39..7ec723d7c 100644 --- a/Projects/Server/Network/Packets/OutgoingAccountPackets.cs +++ b/Projects/Server/Network/Packets/OutgoingAccountPackets.cs @@ -454,7 +454,8 @@ namespace Server.Network writer.WriteAscii(si.Name, 32); writer.Write((byte)si.FullPercent); writer.Write((sbyte)si.TimeZone); - writer.Write(Utility.GetAddressValue(si.Address.Address)); + // UO only supports IPv4 + writer.Write(si.RawAddress); } writer.WritePacketLength(); @@ -477,8 +478,7 @@ namespace Server.Network var writer = new CircularBufferWriter(buffer); writer.Write((byte)0x8C); // Packet ID - var addr = Utility.GetAddressValue(si.Address.Address); - writer.WriteLE(addr); + writer.WriteLE(si.RawAddress); writer.Write((short)si.Address.Port); writer.Write(authId); diff --git a/Projects/Server/Network/ServerInfo.cs b/Projects/Server/Network/ServerInfo.cs index 939cdb841..53f6e7a2f 100644 --- a/Projects/Server/Network/ServerInfo.cs +++ b/Projects/Server/Network/ServerInfo.cs @@ -14,12 +14,15 @@ *************************************************************************/ using System; +using System.Buffers.Binary; using System.Net; namespace Server.Network { public sealed class ServerInfo { + private IPEndPoint m_Address; + public ServerInfo(string name, int fullPercent, TimeZoneInfo tz, IPEndPoint address) { Name = name; @@ -34,6 +37,24 @@ namespace Server.Network public int TimeZone { get; set; } - public IPEndPoint Address { get; set; } + public IPEndPoint Address + { + get => m_Address; + set + { + m_Address = value; + Span integer = stackalloc byte[4]; + value.Address.MapToIPv4().TryWriteBytes(integer, out var bytesWritten); + if (bytesWritten != 4) + { + throw new InvalidOperationException("IP Address could not be serialized to an integer"); + } + + RawAddress = BinaryPrimitives.ReadUInt32LittleEndian(integer); + } + } + + // UO doesn't support IPv6 servers + public uint RawAddress { get; private set; } } } diff --git a/Projects/Server/Serialization/BufferReader.cs b/Projects/Server/Serialization/BufferReader.cs index f0f72fbd7..1255537e9 100644 --- a/Projects/Server/Serialization/BufferReader.cs +++ b/Projects/Server/Serialization/BufferReader.cs @@ -158,7 +158,14 @@ namespace Server return v; } - public IPAddress ReadIPAddress() => new(ReadLong()); + public IPAddress ReadIPAddress() + { + byte length = ReadByte(); + // Either 2 ushorts, or 8 ushorts + Span integer = stackalloc byte[length]; + Read(integer); + return new IPAddress(integer); + } public Point3D ReadPoint3D() => new(ReadInt(), ReadInt(), ReadInt()); diff --git a/Projects/Server/Server.csproj b/Projects/Server/Server.csproj index 0a8e5c9e4..ed620140d 100644 --- a/Projects/Server/Server.csproj +++ b/Projects/Server/Server.csproj @@ -17,6 +17,7 @@ + @@ -27,6 +28,7 @@ + diff --git a/Projects/Server/Utilities/Utility.cs b/Projects/Server/Utilities/Utility.cs index 28dba9de0..16c1bd2d1 100644 --- a/Projects/Server/Utilities/Utility.cs +++ b/Projects/Server/Utilities/Utility.cs @@ -1,4 +1,5 @@ using System; +using System.Buffers.Binary; using System.Collections.Generic; using System.Globalization; using System.IO; @@ -9,6 +10,7 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Text; using System.Xml; +using Microsoft.Toolkit.HighPerformance.Extensions; using Server.Random; namespace Server @@ -183,6 +185,11 @@ namespace Server return null; } + if (ipAddress.IsIPv4MappedToIPv6) + { + ipAddress = ipAddress.MapToIPv4(); + } + _ipAddressTable ??= new Dictionary(); if (!_ipAddressTable.TryGetValue(ipAddress, out var interned)) @@ -199,15 +206,412 @@ namespace Server ipAddress = Intern(ipAddress); } - public static bool IsValidIP(string text) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static uint IPv4ToAddress(IPAddress ipAddress) { - IPMatch(text, IPAddress.None, out var valid); + if (ipAddress.IsIPv4MappedToIPv6) + { + ipAddress = ipAddress.MapToIPv4(); + } + else if (ipAddress.AddressFamily == AddressFamily.InterNetworkV6) + { + return 0; + } - return valid; + Span integer = stackalloc byte[4]; + ipAddress.TryWriteBytes(integer, out var bytesWritten); + return bytesWritten != 4 ? 0 : BinaryPrimitives.ReadUInt32BigEndian(integer); } + public static bool IPMatchClassC(IPAddress ip1, IPAddress ip2) + { + var a = IPv4ToAddress(ip1); + var b = IPv4ToAddress(ip2); + + return a == 0 || b == 0 ? ip1.Equals(ip2) : (a & 0xFFFFFF) == (b & 0xFFFFFF); + } + + public static bool IPMatchCIDR(IPAddress cidrAddress, IPAddress address, int cidrLength) + { + if (cidrAddress.AddressFamily == AddressFamily.InterNetwork) + { + if (address.AddressFamily == AddressFamily.InterNetworkV6) + { + return false; + } + + cidrLength += 96; + } + + cidrAddress = cidrAddress.MapToIPv6(); + address = address.MapToIPv6(); + + cidrLength = Math.Clamp(cidrLength, 0, 128); + + Span cidrBytes = stackalloc byte[16]; + cidrAddress.TryWriteBytes(cidrBytes, out var _); + + Span addrBytes = stackalloc byte[16]; + address.TryWriteBytes(addrBytes, out var _); + + var i = 0; + int offset; + + if (cidrLength < 32) + { + offset = cidrLength; + } + else + { + var index = Math.DivRem(cidrLength, 32, out offset); + while (index > 0) + { + if ( + BinaryPrimitives.ReadInt32BigEndian(cidrBytes.Slice(i, 4)) != + BinaryPrimitives.ReadInt32BigEndian(addrBytes.Slice(i, 4)) + ) + { + return false; + } + + i += 4; + --index; + } + } + + if (offset == 0) + { + return true; + } + + var c = BinaryPrimitives.ReadInt32BigEndian(cidrBytes.Slice(i, 4)); + var a = BinaryPrimitives.ReadInt32BigEndian(addrBytes.Slice(i, 4)); + + var mask = (1 << (32 - offset)) - 1; + var min = ~mask & c; + var max = c | mask; + + return a >= min && a <= max; + } + + public static bool IsValidIP(string val) => IPMatch(val, IPAddress.Any, out var valid) || valid; + public static bool IPMatch(string val, IPAddress ip) => IPMatch(val, ip, out _); + public static bool IPMatch(string val, IPAddress ip, out bool valid) + { + var family = ip.AddressFamily; + var useIPv6 = family == AddressFamily.InterNetworkV6 || val.Contains(':', StringComparison.Ordinal); + + ip = useIPv6 ? ip.MapToIPv6() : ip.MapToIPv4(); + + Span ipBytes = stackalloc byte[useIPv6 ? 16 : 4]; + ip.TryWriteBytes(ipBytes, out _); + + return useIPv6 ? IPv6Match(val, ipBytes, out valid) : IPv4Match(val, ipBytes, out valid); + } + + public static bool IPv4Match(ReadOnlySpan val, ReadOnlySpan ip, out bool valid) + { + var match = true; + valid = true; + var end = val.Length; + var byteIndex = 0; + var section = 0; + var number = 0; + var isRange = false; + var intBase = 10; + var endOfSection = false; + var sectionStart = 0; + + var num = ip[byteIndex++]; + + for (var i = 0; i < end; i++) + { + var chr = val[i]; + if (section >= 4) + { + valid = false; + return false; + } + + switch (chr) + { + default: + { + if (!Uri.IsHexDigit(chr)) + { + valid = false; + return false; + } + + number = number * intBase + Uri.FromHex(chr); + break; + } + case 'x': + case 'X': + { + if (i == sectionStart) + { + intBase = 16; + break; + } + + valid = false; + return false; + } + case '-': + { + if (i == sectionStart || i + 1 == end || val[i + 1] == '.') + { + valid = false; + return false; + } + + // Only allows a single range in a section + if (isRange) + { + valid = false; + return false; + } + + isRange = true; + match = match && num > number; + number = 0; + break; + } + case '*': + { + if (i != sectionStart || i + 1 < end && val[i + 1] != '.') + { + valid = false; + return false; + } + + isRange = true; + number = 255; + break; + } + case '.': + { + endOfSection = true; + break; + } + } + + if (endOfSection || i + 1 == end) + { + if (number < 0 || number > 255) + { + valid = false; + return false; + } + + match = match && (isRange ? num <= number : number == num); + + if (++section < 4) + { + num = ip[byteIndex++]; + } + + intBase = 10; + number = 0; + endOfSection = false; + sectionStart = i + 1; + isRange = false; + } + } + + return match; + } + + public static bool IPv6Match(ReadOnlySpan val, ReadOnlySpan ip, out bool valid) + { + valid = true; + + // Start must be two `::` or a number + if (val[0] == ':' && val[1] != ':') + { + valid = false; + return false; + } + + var match = true; + var end = val.Length; + var byteIndex = 2; + var section = 0; + var number = 0; + var isRange = false; + var endOfSection = false; + var sectionStart = 0; + var hasCompressor = false; + + var num = BinaryPrimitives.ReadUInt16BigEndian(ip.Slice(0, 2)); + + for (int i = 0; i < end; i++) + { + if (section > 7) + { + valid = false; + return false; + } + + var chr = val[i]; + // We are starting a new sequence, check the previous one then continue + switch (chr) + { + default: + { + if (!Uri.IsHexDigit(chr)) + { + valid = false; + return false; + } + + number = number * 16 + Uri.FromHex(chr); + break; + } + case '?': + { + Console.WriteLine("IP Match '?' character is not supported."); + valid = false; + return false; + } + // Range + case '-': + { + if (i == sectionStart || i + 1 == end || val[i + 1] == ':') + { + valid = false; + return false; + } + + // Only allows a single range in a section + if (isRange) + { + valid = false; + return false; + } + + isRange = true; + + // Check low part of the range + match = match && num >= number; + number = 0; + break; + } + // Wild section + case '*': + { + if (i != sectionStart || i + 1 < end && val[i + 1] != ':') + { + valid = false; + return false; + } + + isRange = true; + number = 65535; + break; + } + case ':': + { + endOfSection = true; + break; + } + } + + if (!endOfSection && i + 1 != end) + { + continue; + } + + if (++i == end || val[i] != ':' || section > 0) + { + match = match && (isRange ? num <= number : number == num); + + // IPv4 matching at the end + if (section == 6 && num == 0xFFFF) + { + var ipv4 = val.Slice(i + 1); + if (ipv4.Contains('.')) + { + return IPv4Match(ipv4, ip.Slice(ip.Length - 4), out valid); + } + } + + if (i == end) + { + break; + } + + + num = BinaryPrimitives.ReadUInt16BigEndian(ip.Slice(byteIndex, 2)); + byteIndex += 2; + + ++section; + } + + if (i < end && val[i] == ':') + { + if (hasCompressor) + { + valid = false; + return false; + } + + int newSection; + + if (i + 1 < end) + { + var remainingColons = val.Slice(i + 1).Count(':'); + // double colon must be at least 2 sections + // we need at least 1 section remaining out of 8 + // This means 8 - 2 would be 6 sections (5 colons) + newSection = section + 2 + (5 - remainingColons); + if (newSection > 7) + { + valid = false; + return false; + } + } + else + { + newSection = 7; + } + + var zeroEnd = (newSection + 1) * 2; + do + { + if (match) + { + if (num != 0) + { + match = false; + } + + num = BinaryPrimitives.ReadUInt16BigEndian(ip.Slice(byteIndex, 2)); + } + + byteIndex += 2; + } while (byteIndex < zeroEnd); + + section = newSection; + hasCompressor = true; + } + else + { + i--; + } + + number = 0; + endOfSection = false; + sectionStart = i + 1; + isRange = false; + } + + return match; + } + public static string FixHtml(string str) { if (str == null) @@ -244,311 +648,6 @@ namespace Server return sb.ToString(); } - public static bool IPMatchCIDR(string cidr, IPAddress ip) - { - if (ip == null || ip.AddressFamily == AddressFamily.InterNetworkV6) - { - return false; // Just worry about IPv4 for now - } - - var bytes = new byte[4]; - var split = cidr.Split('.'); - var cidrBits = false; - var cidrLength = 0; - - for (var i = 0; i < 4; i++) - { - var part = 0; - - var partBase = 10; - - var pattern = split[i]; - - for (var j = 0; j < pattern.Length; j++) - { - var c = pattern[j]; - - if (c == 'x' || c == 'X') - { - partBase = 16; - } - else if (c >= '0' && c <= '9') - { - var offset = c - '0'; - - if (cidrBits) - { - cidrLength *= partBase; - cidrLength += offset; - } - else - { - part *= partBase; - part += offset; - } - } - else if (c >= 'a' && c <= 'f') - { - var offset = 10 + (c - 'a'); - - if (cidrBits) - { - cidrLength *= partBase; - cidrLength += offset; - } - else - { - part *= partBase; - part += offset; - } - } - else if (c >= 'A' && c <= 'F') - { - var offset = 10 + (c - 'A'); - - if (cidrBits) - { - cidrLength *= partBase; - cidrLength += offset; - } - else - { - part *= partBase; - part += offset; - } - } - else if (c == '/') - { - if (cidrBits || i != 3) // If there's two '/' or the '/' isn't in the last byte - { - return false; - } - - partBase = 10; - cidrBits = true; - } - else - { - return false; - } - } - - bytes[i] = (byte)part; - } - - return IPMatchCIDR(OrderedAddressValue(bytes), ip, cidrLength); - } - - public static bool IPMatchCIDR(IPAddress cidrPrefix, IPAddress ip, int cidrLength) - { - // Ignore IPv6 for now - if (cidrPrefix == null || ip == null || cidrPrefix.AddressFamily == AddressFamily.InterNetworkV6) - { - return false; - } - - var cidrValue = SwapUnsignedInt((uint)GetLongAddressValue(cidrPrefix)); - var ipValue = SwapUnsignedInt((uint)GetLongAddressValue(ip)); - - return IPMatchCIDR(cidrValue, ipValue, cidrLength); - } - - public static bool IPMatchCIDR(uint cidrPrefixValue, IPAddress ip, int cidrLength) - { - if (ip == null || ip.AddressFamily == AddressFamily.InterNetworkV6) - { - return false; - } - - var ipValue = SwapUnsignedInt((uint)GetLongAddressValue(ip)); - - return IPMatchCIDR(cidrPrefixValue, ipValue, cidrLength); - } - - public static bool IPMatchCIDR(uint cidrPrefixValue, uint ipValue, int cidrLength) - { - if (cidrLength <= 0 || cidrLength >= 32) // if invalid cidr Length, just compare IPs - { - return cidrPrefixValue == ipValue; - } - - var mask = uint.MaxValue << (32 - cidrLength); - - return (cidrPrefixValue & mask) == (ipValue & mask); - } - - private static uint OrderedAddressValue(byte[] bytes) - { - if (bytes.Length != 4) - { - return 0; - } - - return (uint)((bytes[0] << 0x18) | (bytes[1] << 0x10) | (bytes[2] << 8) | bytes[3]) & 0xffffffff; - } - - private static uint SwapUnsignedInt(uint source) => - ((source & 0x000000FF) << 0x18) - | ((source & 0x0000FF00) << 8) - | ((source & 0x00FF0000) >> 8) - | ((source & 0xFF000000) >> 0x18); - - public static bool TryConvertIPv6toIPv4(ref IPAddress address) - { - if (!Socket.OSSupportsIPv6 || address.AddressFamily == AddressFamily.InterNetwork) - { - return true; - } - - var addr = address.GetAddressBytes(); - if (addr.Length == 16) // sanity 0 - 15 //10 11 //12 13 14 15 - { - if (addr[10] != 0xFF || addr[11] != 0xFF) - { - return false; - } - - for (var i = 0; i < 10; i++) - { - if (addr[i] != 0) - { - return false; - } - } - - var v4Addr = new byte[4]; - - for (var i = 0; i < 4; i++) - { - v4Addr[i] = addr[12 + i]; - } - - address = new IPAddress(v4Addr); - return true; - } - - return false; - } - - public static bool IPMatch(string val, IPAddress ip, out bool valid) - { - valid = true; - - var split = val.Split('.'); - - for (var i = 0; i < 4; ++i) - { - int lowPart, highPart; - - if (i >= split.Length) - { - lowPart = 0; - highPart = 255; - } - else - { - var pattern = split[i]; - - if (pattern == "*") - { - lowPart = 0; - highPart = 255; - } - else - { - lowPart = 0; - highPart = 0; - - var highOnly = false; - var lowBase = 10; - var highBase = 10; - - for (var j = 0; j < pattern.Length; ++j) - { - var c = pattern[j]; - - if (c == '?') - { - if (!highOnly) - { - lowPart *= lowBase; - lowPart += 0; - } - - highPart *= highBase; - highPart += highBase - 1; - } - else if (c == '-') - { - highOnly = true; - highPart = 0; - } - else if (c == 'x' || c == 'X') - { - lowBase = 16; - highBase = 16; - } - else if (c >= '0' && c <= '9') - { - var offset = c - '0'; - - if (!highOnly) - { - lowPart *= lowBase; - lowPart += offset; - } - - highPart *= highBase; - highPart += offset; - } - else if (c >= 'a' && c <= 'f') - { - var offset = 10 + (c - 'a'); - - if (!highOnly) - { - lowPart *= lowBase; - lowPart += offset; - } - - highPart *= highBase; - highPart += offset; - } - else if (c >= 'A' && c <= 'F') - { - var offset = 10 + (c - 'A'); - - if (!highOnly) - { - lowPart *= lowBase; - lowPart += offset; - } - - highPart *= highBase; - highPart += offset; - } - else - { - valid = false; // high & lowp art would be 0 if it got to here. - } - } - } - } - - int b = (byte)(GetAddressValue(ip) >> (i * 8)); - - if (b < lowPart || b > highPart) - { - return false; - } - } - - return true; - } - - public static bool IPMatchClassC(IPAddress ip1, IPAddress ip2) => - (GetAddressValue(ip1) & 0xFFFFFF) == (GetAddressValue(ip2) & 0xFFFFFF); - public static int InsensitiveCompare(string first, string second) => Insensitive.Compare(first, second); public static bool InsensitiveStartsWith(string first, string second) => Insensitive.StartsWith(first, second); @@ -1055,10 +1154,6 @@ namespace Server public static string GetText(XmlElement node, string defaultValue) => node?.InnerText ?? defaultValue; - public static int GetAddressValue(IPAddress address) => BitConverter.ToInt32(address.GetAddressBytes(), 0); - - public static long GetLongAddressValue(IPAddress address) => BitConverter.ToInt64(address.GetAddressBytes(), 0); - public static bool InRange(Point3D p1, Point3D p2, int range) => p1.m_X >= p2.m_X - range && p1.m_X <= p2.m_X + range diff --git a/Projects/UOContent/Accounting/Account.cs b/Projects/UOContent/Accounting/Account.cs index 3a234cfb7..904c702d1 100644 --- a/Projects/UOContent/Accounting/Account.cs +++ b/Projects/UOContent/Accounting/Account.cs @@ -1004,7 +1004,7 @@ namespace Server.Accounting for (var i = 0; !accessAllowed && i < IPRestrictions.Length; ++i) { - accessAllowed = Utility.IPMatch(IPRestrictions[i], ipAddress); + accessAllowed = IPAddress.Parse(IPRestrictions[i]).Equals(ipAddress); } return accessAllowed; diff --git a/Projects/UOContent/Accounting/Firewall.cs b/Projects/UOContent/Accounting/Firewall.cs index ae6fbb310..a0ea62f34 100644 --- a/Projects/UOContent/Accounting/Firewall.cs +++ b/Projects/UOContent/Accounting/Firewall.cs @@ -170,26 +170,6 @@ namespace Server } return false; - /* - bool contains = false; - - for ( int i = 0; !contains && i < m_Blocked.Count; ++i ) - { - if (m_Blocked[i] is IPAddress) - contains = ip.Equals( m_Blocked[i] ); - else if (m_Blocked[i] is String) - { - string s = (string)m_Blocked[i]; - - contains = Utility.IPMatchCIDR( s, ip ); - - if (!contains) - contains = Utility.IPMatch( s, ip ); - } - } - - return contains; - * */ } public interface IFirewallEntry