Skip to content

Commit 9e4750f

Browse files
authored
Merge pull request #15 from smdn/ipv4-mapped-ipv6-addrs
Add support for resolving IPv4-mapped IPv6 addresses
2 parents e4ccd63 + e4f53e5 commit 9e4750f

File tree

5 files changed

+149
-4
lines changed

5 files changed

+149
-4
lines changed

src/Smdn.Net.AddressResolution/Smdn.Net.AddressResolution/MacAddressResolver.AddressResolution.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ CancellationToken cancellationToken
3333
if (!FilterAddressTableEntryForAddressResolution(entry))
3434
return false;
3535

36-
if (!entry.Equals(ipAddress))
36+
if (!entry.Equals(ipAddress, shouldConsiderIPv4MappedIPv6Address: ShouldResolveIPv4MappedIPv6Address))
3737
return false;
3838

3939
// ignore the entry that is marked as invalidated

src/Smdn.Net.AddressResolution/Smdn.Net.AddressResolution/MacAddressResolver.cs

+8
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,14 @@ timeStampForFullScan is null || // not performed yet
161161
private const int DefaultParallelCountForRefreshInvalidatedAddresses = 3;
162162
private SemaphoreSlim partialScanSemaphore;
163163

164+
/// <summary>
165+
/// Gets or sets a value indicating whether the address resolution to be aware or not to be aware that
166+
/// the IP address is an IPv4-mapped IPv6 address when resolving IP address to MAC address.
167+
/// </summary>
168+
/// <seealso cref="MacAddressResolverBase.ResolveIPAddressToMacAddressAsync(IPAddress, CancellationToken)" />
169+
/// <seealso cref="AddressTableEntry.Equals(IPAddress?, bool)" />
170+
public bool ShouldResolveIPv4MappedIPv6Address { get; set; }
171+
164172
/// <summary>
165173
/// Initializes a new instance of the <see cref="MacAddressResolver"/> class.
166174
/// </summary>

src/Smdn.Net.AddressResolution/Smdn.Net.AddressTables/AddressTableEntry.cs

+23-3
Original file line numberDiff line numberDiff line change
@@ -73,11 +73,31 @@ public bool Equals(AddressTableEntry other)
7373
=> DefaultEqualityComparer.Equals(this, other);
7474

7575
public bool Equals(IPAddress? other)
76+
=> Equals(other, shouldConsiderIPv4MappedIPv6Address: false);
77+
78+
/// <summary>
79+
/// Indicates whether the member <see cref="AddressTableEntry.IPAddress"/> is equal to the IP address passed to the parameter.
80+
/// </summary>
81+
/// <param name="other">The <see cref="System.Net.IPAddress"/> to be compared with the <see cref="AddressTableEntry.IPAddress"/>.</param>
82+
/// <param name="shouldConsiderIPv4MappedIPv6Address">
83+
/// Specifies whether or not to be aware that the IP address to be an IPv4-mapped IPv6 address or not when comparing IP addresses.
84+
/// </param>
85+
/// <returns>
86+
/// <see langword="true"/> if the <see cref="AddressTableEntry.IPAddress"/> is equal to the <paramref name="other"/> parameter; otherwise, <see langword="false"/>.
87+
/// </returns>
88+
public bool Equals(IPAddress? other, bool shouldConsiderIPv4MappedIPv6Address)
7689
{
77-
if (IPAddress is null)
78-
return other is null;
90+
if (other is null)
91+
return IPAddress is null;
92+
93+
if (shouldConsiderIPv4MappedIPv6Address) {
94+
if (other.IsIPv4MappedToIPv6 && other.MapToIPv4().Equals(IPAddress))
95+
return true;
96+
if (IPAddress is not null && IPAddress.IsIPv4MappedToIPv6 && other.Equals(IPAddress.MapToIPv4()))
97+
return true;
98+
}
7999

80-
return IPAddress.Equals(other);
100+
return other.Equals(IPAddress);
81101
}
82102

83103
public bool Equals(PhysicalAddress? other)

tests/Smdn.Net.AddressResolution/Smdn.Net.AddressResolution/MacAddressResolver.ResolveAsync.cs

+29
Original file line numberDiff line numberDiff line change
@@ -628,4 +628,33 @@ await resolver.ResolveMacAddressToIPAddressAsync(entryToResolve.PhysicalAddress!
628628
Is.EqualTo(expectedEntry.IPAddress)
629629
);
630630
}
631+
632+
[Test]
633+
public async Task ResolveIPAddressToMacAddressAsync_ShouldResolveIPv4MappedIPv6Address(
634+
[Values("127.0.0.1", "192.0.2.0")] string ipv4AddressString,
635+
[Values] bool shouldResolveIPv4MappedIPv6Address
636+
)
637+
{
638+
using var resolver = CreateNullNetworkScannerMacAddressResolver(
639+
new StaticAddressTable([
640+
new(IPAddress.Parse(ipv4AddressString), PhysicalAddress.Parse("00-00-5E-00-53-00"), false, AddressTableEntryState.Reachable, "wlan0"),
641+
])
642+
);
643+
644+
resolver.ShouldResolveIPv4MappedIPv6Address = shouldResolveIPv4MappedIPv6Address;
645+
646+
Assert.That(
647+
await resolver.ResolveIPAddressToMacAddressAsync(IPAddress.Parse(ipv4AddressString)),
648+
Is.Not.Null
649+
);
650+
651+
var ipv4MappedIPv6AddressString = $"::ffff:{ipv4AddressString}";
652+
653+
Assert.That(
654+
await resolver.ResolveIPAddressToMacAddressAsync(IPAddress.Parse(ipv4MappedIPv6AddressString)),
655+
shouldResolveIPv4MappedIPv6Address
656+
? Is.Not.Null
657+
: Is.Null
658+
);
659+
}
631660
}

tests/Smdn.Net.AddressResolution/Smdn.Net.AddressTables/AddressTableEntry.cs

+88
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,94 @@ private static System.Collections.IEnumerable YieldTestCases_Equals_OfIPAddress(
388388
public void Equals_OfIPAddress(AddressTableEntry entry, IPAddress? ipAddress, bool expected)
389389
=> Assert.That(entry.Equals(ipAddress), Is.EqualTo(expected));
390390

391+
private static System.Collections.IEnumerable YieldTestCases_Equals_OfIPAddress_ShouldConsiderIPv4MappedIPv6Address()
392+
{
393+
var ipv4AddressEntry = new AddressTableEntry(
394+
ipAddress: TestIPAddress,
395+
physicalAddress: null,
396+
isPermanent: true,
397+
state: AddressTableEntryState.None,
398+
interfaceId: null
399+
);
400+
var ipv4MappedIPv6AddressEntry = new AddressTableEntry(
401+
ipAddress: TestIPAddress.MapToIPv6(),
402+
physicalAddress: null,
403+
isPermanent: true,
404+
state: AddressTableEntryState.None,
405+
interfaceId: null
406+
);
407+
IPAddress? nullIPAddress = null;
408+
409+
foreach (var shouldConsiderIPv4MappedIPv6Address in new[] { true, false }) {
410+
yield return new object?[] {
411+
ipv4AddressEntry,
412+
nullIPAddress,
413+
shouldConsiderIPv4MappedIPv6Address,
414+
false
415+
};
416+
yield return new object?[] {
417+
ipv4AddressEntry,
418+
ipv4AddressEntry.IPAddress,
419+
shouldConsiderIPv4MappedIPv6Address,
420+
true
421+
};
422+
yield return new object?[] {
423+
ipv4AddressEntry,
424+
ipv4AddressEntry.IPAddress!.MapToIPv6(), // compare with IPv4-mapped IPv6 address
425+
shouldConsiderIPv4MappedIPv6Address,
426+
shouldConsiderIPv4MappedIPv6Address
427+
};
428+
}
429+
430+
foreach (var shouldConsiderIPv4MappedIPv6Address in new[] { true, false }) {
431+
yield return new object?[] {
432+
ipv4MappedIPv6AddressEntry,
433+
nullIPAddress,
434+
shouldConsiderIPv4MappedIPv6Address,
435+
false
436+
};
437+
yield return new object?[] {
438+
ipv4MappedIPv6AddressEntry,
439+
ipv4MappedIPv6AddressEntry.IPAddress,
440+
shouldConsiderIPv4MappedIPv6Address,
441+
true
442+
};
443+
yield return new object?[] {
444+
ipv4MappedIPv6AddressEntry,
445+
ipv4MappedIPv6AddressEntry.IPAddress!.MapToIPv4(), // compare with IPv4-mapped IPv6 address
446+
shouldConsiderIPv4MappedIPv6Address,
447+
shouldConsiderIPv4MappedIPv6Address
448+
};
449+
}
450+
451+
var nullIPAddressEntry = default(AddressTableEntry);
452+
453+
foreach (var shouldConsiderIPv4MappedIPv6Address in new[] { true, false }) {
454+
yield return new object?[] {
455+
nullIPAddressEntry,
456+
nullIPAddress,
457+
shouldConsiderIPv4MappedIPv6Address,
458+
true
459+
};
460+
yield return new object?[] {
461+
nullIPAddressEntry,
462+
TestIPAddress,
463+
shouldConsiderIPv4MappedIPv6Address,
464+
false
465+
};
466+
yield return new object?[] {
467+
nullIPAddressEntry,
468+
TestIPAddress.MapToIPv6(),
469+
shouldConsiderIPv4MappedIPv6Address,
470+
false
471+
};
472+
}
473+
}
474+
475+
[TestCaseSource(nameof(YieldTestCases_Equals_OfIPAddress_ShouldConsiderIPv4MappedIPv6Address))]
476+
public void Equals_OfIPAddress_ShouldConsiderIPv4MappedIPv6Address(AddressTableEntry entry, IPAddress? ipAddress, bool shouldConsiderIPv4MappedIPv6Address, bool expected)
477+
=> Assert.That(entry.Equals(ipAddress, shouldConsiderIPv4MappedIPv6Address), Is.EqualTo(expected));
478+
391479
[Test]
392480
public void Equals_PhysicalAddressNull()
393481
{

0 commit comments

Comments
 (0)