Implement the Mono side of Android support for NetworkInterface.GetAllNetworkInterfac...
authorMarek Habersack <grendel@twistedcode.net>
Fri, 30 May 2014 14:35:56 +0000 (16:35 +0200)
committerMarek Habersack <grendel@twistedcode.net>
Wed, 30 Jul 2014 22:22:33 +0000 (18:22 -0400)
Added code to call Xamarin.Android internal implementation of getifaddrs/freeifaddrs to provide us
with the required information to fulfill the request.

Added a handful of Linux ARP hardware IDs which are considered to be tunnel devices and which may occur
on Android devices.

Part of fix for https://bugzilla.xamarin.com/show_bug.cgi?id=1969

mcs/class/System/System.Net.NetworkInformation/LinuxNetworkInterfaceMarshal.cs
mcs/class/System/System.Net.NetworkInformation/NetworkInterface.cs
mcs/class/System/System/AndroidPlatform.cs

index 249a55b0f4c797b5da567437f68bf79d7c6e180e..feeaec42d509f4abba613260d93cf180fd9b7b71 100644 (file)
@@ -85,8 +85,15 @@ namespace System.Net.NetworkInformation {
                public ushort sll_hatype;
                public byte   sll_pkttype;
                public byte   sll_halen;
-
+#if MONODROID
+               // In MonoDroid the structure has larger space allocated for the address part since there exist
+               // addresses (Infiniband, ipv6 tunnels) which exceed the standard 8 bytes. In fact, glibc's
+               // getifaddrs implementation also uses the bigger size, but for compatibility with other libc
+               // implementations we use the standard address size
+               [MarshalAs (UnmanagedType.ByValArray, SizeConst=24)]
+#else
                [MarshalAs (UnmanagedType.ByValArray, SizeConst=8)]
+#endif
                public byte[] sll_addr;
        }
 
@@ -96,11 +103,18 @@ namespace System.Net.NetworkInformation {
                PRONET = 4,
                ATM = 19,
                SLIP = 256,
+               CSLIP = 257,
+               SLIP6 = 258,
+               CSLIP6 = 259,
                PPP = 512,
                LOOPBACK = 772,
                FDDI = 774,
                TUNNEL = 768,
-               TUNNEL6 = 769
+               TUNNEL6 = 769,
+               SIT = 776, // IPv6-in-IPv4 tunnel
+               IPDDP = 777, // IP over DDP tunnel
+               IPGRE = 778, // GRE over IP
+               IP6GRE = 823 // GRE over IPv6
        }
 }
 
index 18b3b4716421aa12c473d35d771776f3ac25416a..aa7a8969fc6330860bdd32e04a8b496bd408257a 100644 (file)
@@ -238,11 +238,29 @@ namespace System.Net.NetworkInformation {
                        get { return iface_path; }
                }
                
+               static int GetInterfaceAddresses (out IntPtr ifap)
+               {
+#if MONODROID
+                       return AndroidPlatform.GetInterfaceAddresses (out ifap);
+#else
+                       return getifaddrs (out ifap);
+#endif
+               }
+
+               static void FreeInterfaceAddresses (IntPtr ifap)
+               {
+#if MONODROID
+                       AndroidPlatform.FreeInterfaceAddresses (ifap);
+#else
+                       freeifaddrs (ifap);
+#endif
+               }
+               
                public static NetworkInterface [] ImplGetAllNetworkInterfaces ()
                {
                        var interfaces = new Dictionary <string, LinuxNetworkInterface> ();
                        IntPtr ifap;
-                       if (getifaddrs (out ifap) != 0)
+                       if (GetInterfaceAddresses (out ifap) != 0)
                                throw new SystemException ("getifaddrs() failed");
 
                        try {
@@ -295,6 +313,9 @@ namespace System.Net.NetworkInformation {
                                                                                break;
                                                                        
                                                                        case LinuxArpHardware.SLIP:
+                                                                       case LinuxArpHardware.CSLIP:
+                                                                       case LinuxArpHardware.SLIP6:
+                                                                       case LinuxArpHardware.CSLIP6:
                                                                                type = NetworkInterfaceType.Slip;
                                                                                break;
                                                                        
@@ -311,9 +332,11 @@ namespace System.Net.NetworkInformation {
                                                                                type = NetworkInterfaceType.Fddi;
                                                                                break;
 
+                                                                       case LinuxArpHardware.SIT:
+                                                                       case LinuxArpHardware.IPDDP:
+                                                                       case LinuxArpHardware.IPGRE:
+                                                                       case LinuxArpHardware.IP6GRE:
                                                                        case LinuxArpHardware.TUNNEL6:
-                                                                               goto case LinuxArpHardware.TUNNEL;
-                                                                               
                                                                        case LinuxArpHardware.TUNNEL:
                                                                                type = NetworkInterfaceType.Tunnel;
                                                                                break;
@@ -344,7 +367,7 @@ namespace System.Net.NetworkInformation {
                                        next = addr.ifa_next;
                                }
                        } finally {
-                               freeifaddrs (ifap);
+                               FreeInterfaceAddresses (ifap);
                        }
 
                        NetworkInterface [] result = new NetworkInterface [interfaces.Count];
index 45adf27af71cab8fbdc631893eac34ae7266b84a..e2e89448d18c80e02e9a17b116b8e040054e4541 100644 (file)
@@ -38,12 +38,15 @@ using MSX = Mono.Security.X509;
 namespace System {
 
        internal static class AndroidPlatform {
-
+               delegate int GetInterfaceAddressesDelegate (out IntPtr ifap);
+               delegate void FreeInterfaceAddressesDelegate (IntPtr ifap);
+               
 #if SECURITY_DEP
                static readonly Converter<List <byte[]>, bool> trustEvaluateSsl;
 #endif  // SECURITY_DEP
                static readonly Func<IWebProxy> getDefaultProxy;
-
+               static readonly GetInterfaceAddressesDelegate getInterfaceAddresses;
+               static readonly FreeInterfaceAddressesDelegate freeInterfaceAddresses;
 
                static AndroidPlatform ()
                {
@@ -60,6 +63,16 @@ namespace System {
                                typeof (Func<IWebProxy>), t, "GetDefaultProxy",
                                ignoreCase:false,
                                throwOnBindFailure:true);
+
+                       getInterfaceAddresses = (GetInterfaceAddressesDelegate)Delegate.CreateDelegate (
+                               typeof (GetInterfaceAddressesDelegate), t, "GetInterfaceAddresses",
+                               ignoreCase: false,
+                               throwOnBindFailure: false);
+                       
+                       freeInterfaceAddresses = (FreeInterfaceAddressesDelegate)Delegate.CreateDelegate (
+                               typeof (FreeInterfaceAddressesDelegate), t, "FreeInterfaceAddresses",
+                               ignoreCase: false,
+                               throwOnBindFailure: false);
                }
 
 #if SECURITY_DEP
@@ -76,6 +89,23 @@ namespace System {
                {
                        return getDefaultProxy ();
                }
+
+               internal static int GetInterfaceAddresses (out IntPtr ifap)
+               {
+                       ifap = IntPtr.Zero;
+                       if (getInterfaceAddresses == null)
+                               return -1;
+
+                       return getInterfaceAddresses (out ifap);
+               }
+
+               internal static void FreeInterfaceAddresses (IntPtr ifap)
+               {
+                       if (freeInterfaceAddresses == null)
+                               return;
+
+                       freeInterfaceAddresses (ifap);
+               }
        }
 }
 #endif  // MONODROID