Skip to content

Instantly share code, notes, and snippets.

@StephenCleary
Last active February 17, 2022 14:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save StephenCleary/ec47d773a47e6c227eb063d894ea0d4c to your computer and use it in GitHub Desktop.
Save StephenCleary/ec47d773a47e6c227eb063d894ea0d4c to your computer and use it in GitHub Desktop.
Find the local MTU for a hostname/IPv4/IPv6 address
// LINQPad script
async Task Main()
{
byte[] LogicalAnd(byte[] x, byte[] y)
{
var result = new byte[x.Length];
for (int i = 0; i != x.Length; ++i)
result[i] = (byte) (x[i] & y[i]);
return result;
}
bool Equal(byte[] x, byte[] y)
{
for (int i = 0; i != x.Length; ++i)
if (x[i] != y[i])
return false;
return true;
}
byte[] IPv6PrefixMask(int prefixLength)
{
var result = new byte[16];
int index = 0;
while (true)
{
if (prefixLength >= 8)
{
result[index++] = 0xFF;
prefixLength -= 8;
if (prefixLength == 0)
break;
}
else
{
result[index++] = (byte) (0xFF << (8 - prefixLength));
break;
}
}
return result;
}
//var ipAddresses = (await Dns.GetHostAddressesAsync("::1"))
//var ipAddresses = (await Dns.GetHostAddressesAsync("localhost"))
var ipAddresses = (await Dns.GetHostAddressesAsync("www.microsoft.com"))
.Where(x => x.AddressFamily == AddressFamily.InterNetwork || x.AddressFamily == AddressFamily.InterNetworkV6)
.ToList();
ipAddresses.Select(x => x.ToString()).Dump();
var networkInterfacesIPv4 = NetworkInterface.GetAllNetworkInterfaces()
.Where(x => x.Supports(NetworkInterfaceComponent.IPv4))
.Select(x =>
{
var ipProperties = x.GetIPProperties();
return new NetworkAdapter(NetworkInterface: x, IPProperties: ipProperties, IPv4Properties: ipProperties.GetIPv4Properties());
})
.ToList();
var networkInterfacesIPv6 = NetworkInterface.GetAllNetworkInterfaces()
.Where(x => x.Supports(NetworkInterfaceComponent.IPv6))
.Select(x =>
{
var ipProperties = x.GetIPProperties();
return new NetworkAdapter(NetworkInterface: x, IPProperties: ipProperties, IPv6Properties: ipProperties.GetIPv6Properties());
})
.ToList();
var ipAddress = ipAddresses.First();
var isLoopback = ipAddress.Equals(IPAddress.Loopback) || ipAddress.Equals(IPAddress.IPv6Loopback);
var binaryIpAddress = ipAddress.GetAddressBytes();
var networkInterfaces = ipAddress.AddressFamily == AddressFamily.InterNetwork ? networkInterfacesIPv4 : networkInterfacesIPv6;
var compatibleInterfaces = networkInterfaces
.Where(x => (!isLoopback && x.IPProperties.GatewayAddresses.Count != 0) || x.IPProperties.UnicastAddresses.Where(y => y.Address.AddressFamily == ipAddress.AddressFamily).Any(y =>
{
var binaryMask = y.Address.AddressFamily == AddressFamily.InterNetwork ? y.IPv4Mask.GetAddressBytes() : IPv6PrefixMask(y.PrefixLength);
return Equal(LogicalAnd(binaryMask, binaryIpAddress), LogicalAnd(binaryMask, y.Address.GetAddressBytes()));
}));
if (ipAddress.AddressFamily == AddressFamily.InterNetwork)
{
compatibleInterfaces.Select(x => x.NetworkInterface.Name).Dump();
var mtu = compatibleInterfaces.Min(x => (uint)x.IPv4Properties.Mtu);
mtu.Dump();
}
else
{
compatibleInterfaces.Select(x => x.NetworkInterface.Name).Dump();
var mtu = compatibleInterfaces.Min(x => (uint)x.IPv6Properties.Mtu);
mtu.Dump();
}
}
sealed record NetworkAdapter(System.Net.NetworkInformation.NetworkInterface NetworkInterface, IPInterfaceProperties IPProperties, IPv4InterfaceProperties IPv4Properties = null, IPv6InterfaceProperties IPv6Properties = null);
@StephenCleary
Copy link
Author

Fully supports IPv4 and IPv6 addresses and network adapters.

Supports all forms of multihoming, including link aggregation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment