public IPv6Benchmarks() { _net1 = (IpAddressNetworkV6)"2001:db8:8a2e:370::/80"; _address1 = (IpAddressV6)"2001:0db8:8a2e:0370::7334"; _net2 = (IpAddressNetworkV6)"fe80:ffff:1100::/40"; _address2 = (IpAddressV6)"fe80:ffff:1111:2222:3333:4444:5555:6666"; }
public void Setup() { _addressV4 = (IpAddressV4)"174.64.25.18"; _networkV4 = (IpAddressNetworkV4)"174.64.25.18/24"; _addressV6 = (IpAddressV6)"2001:0dff:44ff:0:1744:ffff"; _networkV6 = (IpAddressNetworkV6)"2001:0dff:44ff:0:1744:ffff/64"; _sb = new StringBuilder(); _charBuffer = new char[60]; }
/// <inheritdoc cref="Docs.IIPAddressNetworkDocs{IpAddressNetworkV6}.ContainsOrEqual(IpAddressNetworkV6)"/> public bool ContainsOrEqual(IpAddressNetworkV6 other) { if (other.Mask < _mask) { return(false); } IpAddressV6 sharedNetwork = NetworkMask & other._networkAddress; return(sharedNetwork == _networkAddress); }
public void BasicTest(string test, string expectedNetwork, string expectedEnd, byte expectedMask, string expectedSubnetSize) { IpAddressNetworkV6 net = IpAddressNetworkV6.Parse(test); net.Mask.Should().Be(expectedMask); net.NetworkAddress.Should().Be((IpAddressV6)expectedNetwork); net.EndAddress.Should().Be((IpAddressV6)expectedEnd); BigInteger bigExpectedSubnetSize = BigInteger.Parse(expectedSubnetSize); net.SubnetSize.Should().Be(bigExpectedSubnetSize); }
public void FullPropertyTest() { IpAddressNetworkV6 net = IpAddressNetworkV6.Parse("2001:db8::8a2e:371:7334/96"); net.Mask.Should().Be(96); net.ToString().Should().Be("2001:db8::8a2e:0:0/96"); net.NetworkAddress.Should().Be((IpAddressV6)"2001:db8::8a2e:0:0"); net.EndAddress.Should().Be((IpAddressV6)"2001:db8::8a2e:ffff:ffff"); net.NetworkMask.Should().Be((IpAddressV6)"ffff:ffff:ffff:ffff:ffff:ffff::"); net.NetworkWildcardMask.Should().Be((IpAddressV6)"::ffff:ffff"); net.SubnetSize.Should().Be(4294967296); }
public void ContainsTest(string network, string test, bool shouldContain) { IpAddressNetworkV6 net = (IpAddressNetworkV6)network; IpAddressV6 ip = (IpAddressV6)test; if (shouldContain) { net.Contains(ip).Should().BeTrue(); } else { net.Contains(ip).Should().BeFalse(); } }
public void ValidIPv4InV6FormatTests(string expected, string test, byte cidr) { string expectedWithoutSlash = expected.Split('/').First(); IpAddressNetworkV6 parsed = IpAddressNetworkV6.Parse(test); IPAddress expectedIp = IPAddress.Parse(expectedWithoutSlash); parsed.NetworkAddress.Should().Be(expectedIp); if (cidr == 128) { parsed.EndAddress.Should().Be(expectedIp); } parsed.Mask.Should().Be(cidr); // This representation is special, and should still be the IPv4 in IPv6 mapped expectedIp.ToString().Should().Be(expectedWithoutSlash); parsed.ToString().Should().Be(expected); }
public IpAddressNetworkV6 CurrentIPv6UnstableParser() { return(IpAddressNetworkV6.ParseUnstable("2001:0dff:44ff:0:1744::ffff/64")); }
public void IPv6NetworkFormats(string network) { Assert.True(IpAddressNetworkV6.TryParse(network, out _)); }
internal static bool TryParse(ref Tokenizer tokenizer, out IpAddressNetworkV6 result) { // Shortest IPv6 is 2 chars (::) // Longest regular IPv6 is 43 chars (0000:0000:0000:0000:0000:0000:0000:0000/128) // Longest IPv4 mapped IPv6 is 49 chars (0000:0000:0000:0000:0000:ffff:255.255.255.255/128) if (tokenizer.Length < 2 || tokenizer.Length > 49) { result = default; return(false); } ulong high = 0; ulong low = 0; byte cidr = 128; byte segmentsRead = 0; bool doReverse = false; // First pass, try reading a mask from the end of the input ParsedToken tkn = tokenizer.PeekReverse(false); if (tkn.Type == TokenType.Number) { // Could be a number, therefor a CIDR range or IPv4 ParsedToken slashTkn = tokenizer.PeekReverse(false); if (slashTkn.Type == TokenType.Slash && tkn.Value <= 128) { cidr = (byte)tkn.Value; tokenizer.AdoptPeekOffsets(); } else if (slashTkn.Type == TokenType.Dot) { // This could be an IPv4 mapped in IPv6 // Carry on, see where it gets us tokenizer.ResetPeekOffsets(); } else if (slashTkn.Type != TokenType.Number && slashTkn.Type != TokenType.Colon && slashTkn.Type != TokenType.DoubleColon && slashTkn.Type != TokenType.None) { // Any IPv6 should end on a number or double-colon (excluding the cidr mask), and the cidr mask should be 128 or lower // Single-token IPv6's are allowed, so we check for None as well result = default; return(false); } } // Test if this could be an IPv4 mapped IPv6 // This could be the case if the last two tokens are [Dot, Number] // Like '::ffff:192.168.1.0' tkn = tokenizer.PeekReverse(false); if (tkn.Type == TokenType.Number) { // If the next-to-last is a Dot, pass it on ParsedToken tmpTkn = tokenizer.PeekReverse(false); tokenizer.ResetPeekOffsets(); if (tmpTkn.Type == TokenType.Dot) { return(TryReadIPv4MappedIPv6(ref tokenizer, cidr, out result)); } } tokenizer.ResetPeekOffsets(); // Read up till a double-colon, eof or slash for (byte i = 0; i < 8; i++) { tkn = tokenizer.ParseAndAdvance(true); if (tkn.Type == TokenType.None) { break; } if (i > 0) { // The read token MUST be a colon or a double-colon if (tkn.Type == TokenType.Colon) { // Advance once more tkn = tokenizer.ParseAndAdvance(true); } else if (tkn.Type != TokenType.DoubleColon) { result = default; return(false); } } // Read a number or double-colon if (tkn.Type == TokenType.Number) { BitUtilities.SetTuplet(ref low, ref high, i, tkn.Value); segmentsRead++; } else if (tkn.Type == TokenType.DoubleColon) { doReverse = true; break; } else if (tkn.Type != TokenType.DoubleColon) { result = default; return(false); } } // Read reverse if (doReverse) { byte toRead = (byte)(8 - segmentsRead); for (byte i = 0; i < toRead; i++) { tkn = tokenizer.ParseAndAdvanceReverse(true); if (tkn.Type == TokenType.None) { break; } if (i > 0) { // The read token MUST be a colon if (tkn.Type != TokenType.Colon) { result = default; return(false); } // Advance once more tkn = tokenizer.ParseAndAdvanceReverse(true); } // Read a number if (tkn.Type == TokenType.Number) { BitUtilities.SetTuplet(ref low, ref high, (byte)(7 - i), tkn.Value); segmentsRead++; } else { result = default; return(false); } } } result = new IpAddressNetworkV6(high, low, cidr); return(true); }
public static bool TryParse(ReadOnlySpan <char> value, out IpAddressNetworkV6 result) { Tokenizer tokenizer = new Tokenizer(value); return(TryParse(ref tokenizer, out result)); }
public static bool TryParse(string value, out IpAddressNetworkV6 result) { return(TryParse(value.AsSpan(), out result)); }
public bool IsContainedInOrEqual(IpAddressNetworkV6 other) { return(other.ContainsOrEqual(this)); }
protected override bool Contains(IpAddressNetworkV6 network, IpAddressNetworkV6 other) => network.ContainsOrEqual(other);
[InlineData("2001:0db8::8a2e:192.168.0.1")] // Badly formatted IPv4 in IPv6 public void InvalidFormatsTests(string test) { IpAddressNetworkV6.TryParse(test, out _).Should().BeFalse(); }
public void SplitTest() { // Check that Split fails fast on mask IpAddressNetworkV6 net = (IpAddressNetworkV6)"2001:db8::8a2e:371:7334/96"; Assert.Throws <ArgumentOutOfRangeException>(() => net.Split(128)); Assert.Throws <ArgumentOutOfRangeException>(() => net.Split(33)); Assert.Throws <ArgumentOutOfRangeException>(() => net.Split(0)); // Generic split in the lower-end of the IPv6 struct net = (IpAddressNetworkV6)"2001:db8::8a2e:371:7334/96"; List <IpAddressNetworkV6> splits = net.Split(2).ToList(); splits.Should().ContainInOrder(new IpAddressNetworkV6[] { (IpAddressNetworkV6)"2001:db8::8a2e:0000:0/98", (IpAddressNetworkV6)"2001:db8::8a2e:4000:0/98", (IpAddressNetworkV6)"2001:db8::8a2e:8000:0/98", (IpAddressNetworkV6)"2001:db8::8a2e:c000:0/98" }); // Generic split in the higher-end of the IPv6 struct net = (IpAddressNetworkV6)"2001:db8::/48"; splits = net.Split(2).ToList(); splits.Should().ContainInOrder(new IpAddressNetworkV6[] { (IpAddressNetworkV6)"2001:0db8:0000:0000::/50", (IpAddressNetworkV6)"2001:0db8:0000:4000::/50", (IpAddressNetworkV6)"2001:0db8:0000:8000::/50", (IpAddressNetworkV6)"2001:0db8:0000:c000::/50" }); // Generic split across the two longs in the IPv6 struct net = (IpAddressNetworkV6)"2001:db8:ff32:1234::/63"; splits = net.Split(2).ToList(); splits.Should().ContainInOrder(new IpAddressNetworkV6[] { (IpAddressNetworkV6)"2001:db8:ff32:1234:0000::/65", (IpAddressNetworkV6)"2001:db8:ff32:1234:8000::/65", (IpAddressNetworkV6)"2001:db8:ff32:1235:0000::/65", (IpAddressNetworkV6)"2001:db8:ff32:1235:8000::/65" }); // Major split from ::/0 to ::/128, to ensure it can work (we will _not_ enumerate it) net = (IpAddressNetworkV6)"::/0"; splits = net.Split(128).Take(17).ToList(); splits.Should().ContainInOrder(new IpAddressNetworkV6[] { (IpAddressNetworkV6)"::0/128", (IpAddressNetworkV6)"::1/128", (IpAddressNetworkV6)"::2/128", (IpAddressNetworkV6)"::3/128", (IpAddressNetworkV6)"::4/128", (IpAddressNetworkV6)"::5/128", (IpAddressNetworkV6)"::6/128", (IpAddressNetworkV6)"::7/128", (IpAddressNetworkV6)"::8/128", (IpAddressNetworkV6)"::9/128", (IpAddressNetworkV6)"::A/128", (IpAddressNetworkV6)"::B/128", (IpAddressNetworkV6)"::C/128", (IpAddressNetworkV6)"::D/128", (IpAddressNetworkV6)"::E/128", (IpAddressNetworkV6)"::F/128", (IpAddressNetworkV6)"::10/128" }); }
public IpAddressNetworkV6 Iterative() { IpAddressNetworkV6 ip = IterativeParse("2001:dff:44ff:0:1744::ffff:4d4d/120"); return(ip); }
protected override int Mask(IpAddressNetworkV6 network) => network.Mask;
public bool IsContainedIn(IpAddressNetworkV6 network) => network.Contains(this);
protected override int Compare(IpAddressNetworkV6 network, IpAddressNetworkV6 other) => network.CompareTo(other);
private static bool TryReadIPv4MappedIPv6(ref Tokenizer tokenizer, byte cidr, out IpAddressNetworkV6 result) { ulong high = 0; ulong low = 0; byte segmentsRead = 0; ParsedToken token; // Read reverse, we're only interested in the IPv4 on the end byte toRead = 4; for (byte i = 0; i < toRead; i++) { token = tokenizer.ParseAndAdvanceReverse(false); if (token.Type == TokenType.None) { break; } if (i > 0) { // The read token MUST be a dot if (token.Type != TokenType.Dot) { result = default; return(false); } // Advance once more token = tokenizer.ParseAndAdvanceReverse(false); } // Read a number if (token.Type == TokenType.Number) { BitUtilities.SetByte(ref low, ref high, (byte)(15 - i), token.Value); segmentsRead++; } else { result = default; return(false); } } // Assert that the next tokens are [Double-/Colon, ffff, Colon] token = tokenizer.ParseAndAdvanceReverse(false); if (token.Type != TokenType.Colon) { result = default; return(false); } token = tokenizer.ParseAndAdvanceReverse(true); if (token.Type != TokenType.Number || token.Value != 0xffff) { result = default; return(false); } token = tokenizer.ParseAndAdvanceReverse(false); if (token.Type is not TokenType.Colon && token.Type is not TokenType.DoubleColon) { result = default; return(false); } // Place 0xFFFF in the correct position BitUtilities.SetTuplet(ref low, ref high, 5, 0xFFFF); result = new IpAddressNetworkV6(high, low, cidr); return(true); }