Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,34 @@ internal static partial class IpHlpApi
public const int MAX_DOMAIN_NAME_LEN = 128;
public const int MAX_SCOPE_ID_LEN = 256;

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct FIXED_INFO
[StructLayout(LayoutKind.Sequential)]
public unsafe struct FIXED_INFO
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_HOSTNAME_LEN + 4)]
public string hostName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_DOMAIN_NAME_LEN + 4)]
public string domainName;
private fixed byte _hostName[MAX_HOSTNAME_LEN + 4];
public string HostName => CreateString(ref _hostName[0], MAX_HOSTNAME_LEN + 4);

private fixed byte _domainName[MAX_DOMAIN_NAME_LEN + 4];
public string DomainName => CreateString(ref _domainName[0], MAX_DOMAIN_NAME_LEN + 4);

public IntPtr currentDnsServer; // IpAddressList*
public IP_ADDR_STRING DnsServerList;
public uint nodeType;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_SCOPE_ID_LEN + 4)]
public string scopeId;
public bool enableRouting;
public bool enableProxy;
public bool enableDns;

private fixed byte _scopeId[MAX_SCOPE_ID_LEN + 4];
public string ScopeId => CreateString(ref _scopeId[0], MAX_SCOPE_ID_LEN + 4);

public uint enableRouting;
public uint enableProxy;
public uint enableDns;

private static string CreateString(ref byte firstByte, int maxLength)
{
fixed (byte* ptr = &firstByte)
{
int terminator = new ReadOnlySpan<byte>(ptr, maxLength).IndexOf((byte)0);
return Marshal.PtrToStringAnsi((IntPtr)ptr, (terminator >= 0) ? terminator : maxLength);
}
}
}
}
}
18 changes: 13 additions & 5 deletions src/libraries/Common/src/Interop/Windows/IpHlpApi/Interop.ICMP.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,21 @@ internal struct IcmpEchoReply
}

[StructLayout(LayoutKind.Sequential, Pack = 1)]
internal struct Ipv6Address
internal unsafe struct Ipv6Address
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
internal byte[] Goo;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
internal fixed byte Goo[6];

// Replying address.
internal byte[] Address;
private fixed byte _Address[16];
internal byte[] Address
{
get
{
fixed (byte* pAddress = _Address)
return new ReadOnlySpan<byte>(pAddress, 16).ToArray();
}
}

internal uint ScopeID;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,12 @@ internal static partial class Interop
{
internal static partial class IpHlpApi
{
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct IP_ADDR_STRING
[StructLayout(LayoutKind.Sequential)]
public unsafe struct IP_ADDR_STRING
{
public IntPtr Next; // struct _IpAddressList*
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
public string IpAddress;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
public string IpMask;
public IP_ADDR_STRING* Next;
public fixed byte IpAddress[16];
public fixed byte IpMask[16];
public uint Context;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,61 +12,113 @@ namespace System.Net.NetworkInformation
internal static class HostInformationPal
{
// Changing this information requires a reboot, so it's safe to cache.
private static Interop.IpHlpApi.FIXED_INFO s_fixedInfo;
private static bool s_fixedInfoInitialized;
private static string? s_hostName;
private static string? s_domainName;
private static uint s_nodeType;
private static string? s_scopeId;
private static bool s_enableRouting;
private static bool s_enableProxy;
private static bool s_enableDns;

private static volatile bool s_initialized;
private static object s_syncObject = new object();

public static string GetHostName()
{
return FixedInfo.hostName;
EnsureInitialized();
return s_hostName!;
}

public static string GetDomainName()
{
return FixedInfo.domainName;
EnsureInitialized();
return s_domainName!;
}

public static uint GetNodeType()
{
EnsureInitialized();
return s_nodeType;
}

public static string GetScopeId()
{
EnsureInitialized();
return s_scopeId!;
}

public static bool GetEnableRouting()
{
EnsureInitialized();
return s_enableRouting;
}

private static unsafe Interop.IpHlpApi.FIXED_INFO GetFixedInfo()
public static bool GetEnableProxy()
{
uint size = 0;
Interop.IpHlpApi.FIXED_INFO fixedInfo = default;
EnsureInitialized();
return s_enableProxy;
}

// First we need to get the size of the buffer
uint result = Interop.IpHlpApi.GetNetworkParams(IntPtr.Zero, &size);
public static bool GetEnableDns()
{
EnsureInitialized();
return s_enableDns;
}

while (result == Interop.IpHlpApi.ERROR_BUFFER_OVERFLOW)
private static void EnsureInitialized()
{
if (!s_initialized)
Initialize();
}

private static unsafe void Initialize()
{
lock (s_syncObject)
{
IntPtr buffer = Marshal.AllocHGlobal((int)size);
try
if (s_initialized)
return;

uint size = 0;

// First we need to get the size of the buffer
uint result = Interop.IpHlpApi.GetNetworkParams(IntPtr.Zero, &size);

while (result == Interop.IpHlpApi.ERROR_BUFFER_OVERFLOW)
{
result = Interop.IpHlpApi.GetNetworkParams(buffer, &size);
if (result == Interop.IpHlpApi.ERROR_SUCCESS)
IntPtr buffer = Marshal.AllocHGlobal((int)size);
try
{
fixedInfo = Marshal.PtrToStructure<Interop.IpHlpApi.FIXED_INFO>(buffer);
result = Interop.IpHlpApi.GetNetworkParams(buffer, &size);
if (result == Interop.IpHlpApi.ERROR_SUCCESS)
{
Interop.IpHlpApi.FIXED_INFO* pFixedInfo = (Interop.IpHlpApi.FIXED_INFO*)buffer;

s_hostName = pFixedInfo->HostName;
s_domainName = pFixedInfo->DomainName;

s_hostName = pFixedInfo->HostName;
s_domainName = pFixedInfo->DomainName;
s_nodeType = pFixedInfo->nodeType;
s_scopeId = pFixedInfo->ScopeId;
s_enableRouting = pFixedInfo->enableRouting != 0;
s_enableProxy = pFixedInfo->enableProxy != 0;
s_enableDns = pFixedInfo->enableDns != 0;

s_initialized = true;
}
}
finally
{
Marshal.FreeHGlobal(buffer);
}
}
finally

// If the result include there being no information, we'll still throw
if (result != Interop.IpHlpApi.ERROR_SUCCESS)
{
Marshal.FreeHGlobal(buffer);
throw new Win32Exception((int)result);
}
}

// If the result include there being no information, we'll still throw
if (result != Interop.IpHlpApi.ERROR_SUCCESS)
{
throw new Win32Exception((int)result);
}

return fixedInfo;
}

public static ref readonly Interop.IpHlpApi.FIXED_INFO FixedInfo
{
get
{
LazyInitializer.EnsureInitialized(ref s_fixedInfo, ref s_fixedInfoInitialized, ref s_syncObject, () => GetFixedInfo());
return ref s_fixedInfo;
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public override string HostName
{
get
{
return HostInformationPal.FixedInfo.hostName;
return HostInformationPal.GetHostName();
}
}

Expand All @@ -28,7 +28,7 @@ public override string DomainName
{
get
{
return HostInformationPal.FixedInfo.domainName;
return HostInformationPal.GetDomainName();
}
}

Expand All @@ -48,7 +48,7 @@ public override NetBiosNodeType NodeType
{
get
{
return (NetBiosNodeType)HostInformationPal.FixedInfo.nodeType;
return (NetBiosNodeType)HostInformationPal.GetNodeType();
}
}

Expand All @@ -57,7 +57,7 @@ public override string DhcpScopeName
{
get
{
return HostInformationPal.FixedInfo.scopeId;
return HostInformationPal.GetScopeId();
}
}

Expand All @@ -66,7 +66,7 @@ public override bool IsWinsProxy
{
get
{
return (HostInformationPal.FixedInfo.enableProxy);
return HostInformationPal.GetEnableProxy();
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,11 @@ internal sealed class SystemIPInterfaceProperties : IPInterfaceProperties
private readonly GatewayIPAddressInformationCollection _gatewayAddresses;
private readonly InternalIPAddressCollection _dhcpServers;

internal SystemIPInterfaceProperties(in Interop.IpHlpApi.FIXED_INFO fixedInfo, in Interop.IpHlpApi.IpAdapterAddresses ipAdapterAddresses)
internal SystemIPInterfaceProperties(in Interop.IpHlpApi.IpAdapterAddresses ipAdapterAddresses)
{
_adapterFlags = ipAdapterAddresses.flags;
_dnsSuffix = ipAdapterAddresses.DnsSuffix;
_dnsEnabled = fixedInfo.enableDns;
_dnsEnabled = HostInformationPal.GetEnableDns();
_dynamicDnsEnabled = ((ipAdapterAddresses.flags & Interop.IpHlpApi.AdapterFlags.DnsEnabled) > 0);

_multicastAddresses = SystemMulticastIPAddressInformation.ToMulticastIpAddressInformationCollection(
Expand Down Expand Up @@ -58,7 +58,7 @@ internal SystemIPInterfaceProperties(in Interop.IpHlpApi.FIXED_INFO fixedInfo, i

if ((_adapterFlags & Interop.IpHlpApi.AdapterFlags.IPv4Enabled) != 0)
{
_ipv4Properties = new SystemIPv4InterfaceProperties(fixedInfo, ipAdapterAddresses);
_ipv4Properties = new SystemIPv4InterfaceProperties(ipAdapterAddresses);
}

if ((_adapterFlags & Interop.IpHlpApi.AdapterFlags.IPv6Enabled) != 0)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ internal sealed class SystemIPv4InterfaceProperties : IPv4InterfaceProperties
private bool _autoConfigEnabled;
private bool _autoConfigActive;

internal SystemIPv4InterfaceProperties(Interop.IpHlpApi.FIXED_INFO fixedInfo, Interop.IpHlpApi.IpAdapterAddresses ipAdapterAddresses)
internal SystemIPv4InterfaceProperties(in Interop.IpHlpApi.IpAdapterAddresses ipAdapterAddresses)
{
_index = ipAdapterAddresses.index;
_routingEnabled = fixedInfo.enableRouting;
_routingEnabled = HostInformationPal.GetEnableRouting();
_dhcpEnabled = ((ipAdapterAddresses.flags & Interop.IpHlpApi.AdapterFlags.DhcpEnabled) != 0);
_haveWins = (ipAdapterAddresses.firstWinsServerAddress != IntPtr.Zero);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,6 @@ internal static unsafe NetworkInterface[] GetNetworkInterfaces()
AddressFamily family = AddressFamily.Unspecified;
uint bufferSize = 0;

ref readonly Interop.IpHlpApi.FIXED_INFO fixedInfo = ref HostInformationPal.FixedInfo;
List<SystemNetworkInterface> interfaceList = new List<SystemNetworkInterface>();

Interop.IpHlpApi.GetAdaptersAddressesFlags flags =
Expand Down Expand Up @@ -113,7 +112,7 @@ internal static unsafe NetworkInterface[] GetNetworkInterfaces()
while (adapterAddresses != null)
{
// Traverse the list, marshal in the native structures, and create new NetworkInterfaces.
interfaceList.Add(new SystemNetworkInterface(in fixedInfo, in *adapterAddresses));
interfaceList.Add(new SystemNetworkInterface(in *adapterAddresses));
adapterAddresses = adapterAddresses->next;
}
}
Expand All @@ -139,7 +138,7 @@ internal static unsafe NetworkInterface[] GetNetworkInterfaces()
return interfaceList.ToArray();
}

internal SystemNetworkInterface(in Interop.IpHlpApi.FIXED_INFO fixedInfo, in Interop.IpHlpApi.IpAdapterAddresses ipAdapterAddresses)
internal SystemNetworkInterface(in Interop.IpHlpApi.IpAdapterAddresses ipAdapterAddresses)
{
// Store the common API information.
_id = ipAdapterAddresses.AdapterName;
Expand All @@ -157,7 +156,7 @@ internal SystemNetworkInterface(in Interop.IpHlpApi.FIXED_INFO fixedInfo, in Int
_ipv6Index = ipAdapterAddresses.ipv6Index;

_adapterFlags = ipAdapterAddresses.flags;
_interfaceProperties = new SystemIPInterfaceProperties(fixedInfo, ipAdapterAddresses);
_interfaceProperties = new SystemIPInterfaceProperties(ipAdapterAddresses);
}

public override string Id { get { return _id; } }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -203,18 +203,18 @@ private int SendEcho(IPAddress address, byte[] buffer, int timeout, PingOptions?
(uint)timeout);
}

private PingReply CreatePingReply()
private unsafe PingReply CreatePingReply()
{
SafeLocalAllocHandle buffer = _replyBuffer!;

// Marshals and constructs new reply.
if (_ipv6)
{
Interop.IpHlpApi.Icmp6EchoReply icmp6Reply = Marshal.PtrToStructure<Interop.IpHlpApi.Icmp6EchoReply>(buffer.DangerousGetHandle());
Interop.IpHlpApi.Icmp6EchoReply icmp6Reply = *(Interop.IpHlpApi.Icmp6EchoReply*)buffer.DangerousGetHandle();
return CreatePingReplyFromIcmp6EchoReply(icmp6Reply, buffer.DangerousGetHandle(), _sendSize);
}

Interop.IpHlpApi.IcmpEchoReply icmpReply = Marshal.PtrToStructure<Interop.IpHlpApi.IcmpEchoReply>(buffer.DangerousGetHandle());
Interop.IpHlpApi.IcmpEchoReply icmpReply = *(Interop.IpHlpApi.IcmpEchoReply*)buffer.DangerousGetHandle();
return CreatePingReplyFromIcmpEchoReply(icmpReply);
}

Expand Down