{
internal abstract class UnixNetworkInterfaceAPI : NetworkInterfaceFactory
{
+#if ORBIS
+ public static int if_nametoindex(string ifname)
+ {
+ throw new PlatformNotSupportedException ();
+ }
+
+ protected static int getifaddrs (out IntPtr ifap)
+ {
+ throw new PlatformNotSupportedException ();
+ }
+
+ protected static void freeifaddrs (IntPtr ifap)
+ {
+ throw new PlatformNotSupportedException ();
+ }
+#else
[DllImport("libc")]
public static extern int if_nametoindex(string ifname);
[DllImport ("libc")]
protected static extern void freeifaddrs (IntPtr ifap);
+#endif
}
class MacOsNetworkInterfaceAPI : UnixNetworkInterfaceAPI
} else if (sockaddr.sin_family == AF_PACKET) {
sockaddr_ll sockaddrll = (sockaddr_ll) Marshal.PtrToStructure (addr.ifa_addr, typeof (sockaddr_ll));
if (((int)sockaddrll.sll_halen) > sockaddrll.sll_addr.Length){
- Console.Error.WriteLine ("Got a bad hardware address length for an AF_PACKET {0} {1}",
- sockaddrll.sll_halen, sockaddrll.sll_addr.Length);
next = addr.ifa_next;
continue;
}
}
}
-#if !MOBILE
+#if WIN_PLATFORM
class Win32NetworkInterfaceAPI : NetworkInterfaceFactory
{
- [DllImport ("iphlpapi.dll", SetLastError = true)]
- static extern int GetAdaptersAddresses (uint family, uint flags, IntPtr reserved, byte [] info, ref int size);
+ private const string IPHLPAPI = "iphlpapi.dll";
- unsafe static Win32_IP_ADAPTER_ADDRESSES [] GetAdaptersAddresses ()
+ [DllImport (IPHLPAPI, SetLastError = true)]
+ static extern int GetAdaptersAddresses (uint family, uint flags, IntPtr reserved, IntPtr info, ref int size);
+
+ [DllImport (IPHLPAPI)]
+ static extern uint GetBestInterfaceEx (byte[] ipAddress, out int index);
+
+ static Win32_IP_ADAPTER_ADDRESSES [] GetAdaptersAddresses ()
{
- byte [] bytes = null;
+ IntPtr ptr = IntPtr.Zero;
int len = 0;
- GetAdaptersAddresses (0, 0, IntPtr.Zero, bytes, ref len);
- bytes = new byte [len];
- int ret = GetAdaptersAddresses (0, 0, IntPtr.Zero, bytes, ref len);
+ GetAdaptersAddresses (0, 0, IntPtr.Zero, ptr, ref len);
+ ptr = Marshal.AllocHGlobal(len);
+ int ret = GetAdaptersAddresses (0, 0, IntPtr.Zero, ptr, ref len);
if (ret != 0)
throw new NetworkInformationException (ret);
List<Win32_IP_ADAPTER_ADDRESSES> l = new List<Win32_IP_ADAPTER_ADDRESSES> ();
- fixed (byte* ptr = bytes) {
- Win32_IP_ADAPTER_ADDRESSES info;
- for (IntPtr p = (IntPtr) ptr; p != IntPtr.Zero; p = info.Next) {
- info = new Win32_IP_ADAPTER_ADDRESSES ();
- Marshal.PtrToStructure (p, info);
- l.Add (info);
- }
+ Win32_IP_ADAPTER_ADDRESSES info;
+ for (IntPtr p = ptr; p != IntPtr.Zero; p = info.Next) {
+ info = Marshal.PtrToStructure<Win32_IP_ADAPTER_ADDRESSES> (p);
+ l.Add (info);
}
+
return l.ToArray ();
}
return ret;
}
+ private static int GetBestInterfaceForAddress (IPAddress addr) {
+ int index;
+ SocketAddress address = new SocketAddress (addr);
+ int error = (int) GetBestInterfaceEx (address.m_Buffer, out index);
+ if (error != 0) {
+ throw new NetworkInformationException (error);
+ }
+
+ return index;
+ }
+
public override int GetLoopbackInterfaceIndex ()
{
- throw new NotImplementedException ();
+ return GetBestInterfaceForAddress (IPAddress.Loopback);
}
public override IPAddress GetNetMask (IPAddress address)
#if MONOTOUCH || XAMMAC
return new MacOsNetworkInterfaceAPI ();
#else
- Version windowsVer51 = new Version (5, 1);
bool runningOnUnix = (Environment.OSVersion.Platform == PlatformID.Unix);
if (runningOnUnix) {
return new LinuxNetworkInterfaceAPI ();
}
-#if !MOBILE
+#if WIN_PLATFORM
+ Version windowsVer51 = new Version (5, 1);
if (Environment.OSVersion.Version >= windowsVer51)
return new Win32NetworkInterfaceAPI ();
#endif
string iface_operstate_path;
string iface_flags_path;
+#if MONODROID
+ [DllImport ("__Internal")]
+ static extern int _monodroid_get_android_api_level ();
+
+ [DllImport ("__Internal")]
+ static extern bool _monodroid_get_network_interface_up_state (string ifname, ref bool is_up);
+
+ [DllImport ("__Internal")]
+ static extern bool _monodroid_get_network_interface_supports_multicast (string ifname, ref bool supports_multicast);
+
+ bool android_use_java_api;
+#endif
+
internal string IfacePath {
get { return iface_path; }
}
iface_path = "/sys/class/net/" + name + "/";
iface_operstate_path = iface_path + "operstate";
iface_flags_path = iface_path + "flags";
+#if MONODROID
+ android_use_java_api = _monodroid_get_android_api_level () >= 24;
+#endif
}
public override IPInterfaceProperties GetIPProperties ()
public override OperationalStatus OperationalStatus {
get {
+#if MONODROID
+ if (android_use_java_api) {
+ // Starting from API 24 (Android 7 "Nougat") Android restricts access to many
+ // files in the /sys filesystem (see https://code.google.com/p/android/issues/detail?id=205565
+ // for more information) and therefore we are forced to call into Java API in
+ // order to get the information. Alas, what we can obtain in this way is quite
+ // limited. In the case of OperationalStatus we can only determine whether the
+ // interface is up or down. There is a way to get more detailed information but
+ // it requires an instance of the Android Context class which is not available
+ // to us here.
+ bool is_up = false;
+ if (_monodroid_get_network_interface_up_state (Name, ref is_up))
+ return is_up ? OperationalStatus.Up : OperationalStatus.Down;
+ else
+ return OperationalStatus.Unknown;
+ }
+#endif
if (!Directory.Exists (iface_path))
return OperationalStatus.Unknown;
public override bool SupportsMulticast {
get {
+#if MONODROID
+ if (android_use_java_api) {
+ // Starting from API 24 (Android 7 "Nougat") Android restricts access to many
+ // files in the /sys filesystem (see https://code.google.com/p/android/issues/detail?id=205565
+ // for more information) and therefore we are forced to call into Java API in
+ // order to get the information.
+ bool supports_multicast = false;
+ _monodroid_get_network_interface_supports_multicast (Name, ref supports_multicast);
+ return supports_multicast;
+ }
+#endif
if (!Directory.Exists (iface_path))
return false;
}
}
-#if !MOBILE
+#if WIN_PLATFORM
class Win32NetworkInterface2 : NetworkInterface
{
[DllImport ("iphlpapi.dll", SetLastError = true)]
- static extern int GetAdaptersInfo (byte [] info, ref int size);
+ static extern int GetAdaptersInfo (IntPtr info, ref int size);
[DllImport ("iphlpapi.dll", SetLastError = true)]
static extern int GetIfEntry (ref Win32_MIB_IFROW row);
foreach (Win32_IP_ADAPTER_INFO info in GetAdaptersInfo ())
if (info.Index == index)
return info;
- return null;
+ throw new IndexOutOfRangeException ("No adapter found for index " + index);
}
- unsafe static Win32_IP_ADAPTER_INFO [] GetAdaptersInfo ()
+ static Win32_IP_ADAPTER_INFO [] GetAdaptersInfo ()
{
- byte [] bytes = null;
int len = 0;
- GetAdaptersInfo (bytes, ref len);
- bytes = new byte [len];
- int ret = GetAdaptersInfo (bytes, ref len);
+ IntPtr ptr = IntPtr.Zero;
+ GetAdaptersInfo (ptr, ref len);
+ ptr = Marshal.AllocHGlobal(len);
+ int ret = GetAdaptersInfo (ptr, ref len);
if (ret != 0)
throw new NetworkInformationException (ret);
List<Win32_IP_ADAPTER_INFO> l = new List<Win32_IP_ADAPTER_INFO> ();
- fixed (byte* ptr = bytes) {
- Win32_IP_ADAPTER_INFO info;
- for (IntPtr p = (IntPtr) ptr; p != IntPtr.Zero; p = info.Next) {
- info = new Win32_IP_ADAPTER_INFO ();
- Marshal.PtrToStructure (p, info);
- l.Add (info);
- }
+ Win32_IP_ADAPTER_INFO info;
+ for (IntPtr p = ptr; p != IntPtr.Zero; p = info.Next) {
+ info = Marshal.PtrToStructure<Win32_IP_ADAPTER_INFO> (p);
+ l.Add (info);
}
return l.ToArray ();
}