fix(core): Adds IPv6 support (#348)

## Breaking Change
* IP Matching no longer supports `?` (e.g. you cannot do: "192.16?.0.1")
* IP Matching no longer supports `*` and other values in the same section (e.g. you cannot do "192.1\*.0.1")
  * To do "192.1\*.0.1", you should use the range option with three separate entries: "192.100-199.0.1", "192.1.0.1", "192.10-19.0.1"

## Non-Breaking Changes
- [X] Adds IPv6 support (not for servers though, just clients)
- [X] Adds interning support for IPv4 mapped to IPv6
- [X] Updates IPv4ToAddress (don't use this unless you know it is IPv4 or IPv4 mapped to IPv6)

## Note:
UO Does not support IPv6 for the server. To support an IPv6 server IP you will need to use CUO or some kind of custom client and probably modify it accordingly.

Bumps release version
This commit is contained in:
Kamron Batman 2020-12-19 00:27:39 -08:00 committed by GitHub
parent baf724ead8
commit 92aae8d482
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 527 additions and 342 deletions

1
.gitignore vendored
View file

@ -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

View file

@ -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));

View file

@ -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();
}

View file

@ -1,7 +1,7 @@
using System;
using Xunit;
namespace Server.Tests.Accounting
namespace Server.Tests
{
public class HexStringConverterTest
{

View file

@ -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<byte> integer = stackalloc byte[4];
expected.TryWriteBytes(integer, out _);
Assert.Equal(BinaryPrimitives.ReadUInt32BigEndian(integer), Utility.IPv4ToAddress(ip));
}
}
}

View file

@ -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);

View file

@ -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<byte> 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; }
}
}

View file

@ -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<byte> integer = stackalloc byte[length];
Read(integer);
return new IPAddress(integer);
}
public Point3D ReadPoint3D() => new(ReadInt(), ReadInt(), ReadInt());

View file

@ -17,6 +17,7 @@
<Delete Files="..\..\Distribution\libz.dylib" ContinueOnError="true" />
<Delete Files="..\..\Distribution\libz.so" ContinueOnError="true" />
<Delete Files="..\..\Distribution\ZLib.Bindings.dll" ContinueOnError="true" />
<Delete Files="..\..\Distribution\Microsoft.Toolkit.HighPerformance.dll" ContinueOnError="true" />
<Delete Files="..\..\Distribution\$(AssemblyName)" ContinueOnError="true" />
<Delete Files="..\..\Distribution\$(AssemblyName).dll" ContinueOnError="true" />
<Delete Files="..\..\Distribution\$(AssemblyName).dll.config" ContinueOnError="true" />
@ -27,6 +28,7 @@
<Delete Files="..\..\Distribution\$(AssemblyName).runtimeconfig.json" ContinueOnError="true" />
</Target>
<ItemGroup>
<PackageReference Include="Microsoft.Toolkit.HighPerformance" Version="7.0.0-preview4" />
<PackageReference Include="Zlib.Bindings" Version="1.4.0" />
</ItemGroup>
</Project>

View file

@ -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<IPAddress, IPAddress>();
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<byte> 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<byte> cidrBytes = stackalloc byte[16];
cidrAddress.TryWriteBytes(cidrBytes, out var _);
Span<byte> 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<byte> 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<char> val, ReadOnlySpan<byte> 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<char> val, ReadOnlySpan<byte> 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

View file

@ -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;

View file

@ -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