public unsafe static NetworkInterface[] GetLinuxNetworkInterfaces()
{
Dictionary<string, LinuxNetworkInterface> interfacesByName = new Dictionary<string, LinuxNetworkInterface>();
List<Exception> exceptions = null;
const int MaxTries = 3;
for (int attempt = 0; attempt < MaxTries; attempt++)
{
// Because these callbacks are executed in a reverse-PInvoke, we do not want any exceptions
// to propogate out, because they will not be catchable. Instead, we track all the exceptions
// that are thrown in these callbacks, and aggregate them at the end.
int result = Interop.Sys.EnumerateInterfaceAddresses(
(name, ipAddr, maskAddr) =>
{
try
{
LinuxNetworkInterface lni = GetOrCreate(interfacesByName, name);
lni.ProcessIpv4Address(ipAddr, maskAddr);
}
catch (Exception e)
{
if (exceptions == null)
{
exceptions = new List<Exception>();
}
exceptions.Add(e);
}
},
(name, ipAddr, scopeId) =>
{
try
{
LinuxNetworkInterface lni = GetOrCreate(interfacesByName, name);
lni.ProcessIpv6Address(ipAddr, *scopeId);
}
catch (Exception e)
{
if (exceptions == null)
{
exceptions = new List<Exception>();
}
exceptions.Add(e);
}
},
(name, llAddr) =>
{
try
{
LinuxNetworkInterface lni = GetOrCreate(interfacesByName, name);
lni.ProcessLinkLayerAddress(llAddr);
}
catch (Exception e)
{
if (exceptions == null)
{
exceptions = new List<Exception>();
}
exceptions.Add(e);
}
});
if (exceptions != null)
{
throw new NetworkInformationException(SR.net_PInvokeError, new AggregateException(exceptions));
}
else if (result == 0)
{
return interfacesByName.Values.ToArray();
}
else
{
interfacesByName.Clear();
}
}
throw new NetworkInformationException(SR.net_PInvokeError);
}