Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NetworkInterface.GetAllNetworkInterfaces on Android Throws Null Exception #58374

Closed
SteveBush opened this issue Aug 30, 2021 · 7 comments · Fixed by #63633
Closed

NetworkInterface.GetAllNetworkInterfaces on Android Throws Null Exception #58374

SteveBush opened this issue Aug 30, 2021 · 7 comments · Fixed by #63633

Comments

@SteveBush
Copy link

SteveBush commented Aug 30, 2021

Steps To Reproduce:

  1. Dotnet new android
  2. Add to csproj so LaunchProfiles start up
  <PropertyGroup>
    <_KeepLaunchProfiles>true</_KeepLaunchProfiles>
  </PropertyGroup>
  1. Modify MainActivity.cs by adding the following code.
  2. Build and Run in Visual Studio 17.0.0 Preview 3.1

Result:

An exception is thrown and is null

Expected:

  • No exception and results of NetworkInterface.GetAllNetworkInterfaces to be returned.

Related to System.Net.NetworkInformation needs Android PAL #51303
The System.Net.NetworkInformation APIs stopped working on Android. I have provided a simple repo. This is related to issue System.Net.NetworkInformation needs Android PAL #51303.

In the code below, a null exception is thrown. I have also seen the following exception in another project:
NetworkInformation.NetworkInformationException : No such file or directory

Suggestions:

I'm writing a mobile and desktop networking application so it would be helpful for the System.NetworkInterface APIs to work cross platform. Android stopped providing direct access to the system files in API level 24.

However, Android includes the ip and ifconfig commands which essentially read the contents of these protected system files and could be used to create a NetworkInterface on Android. See output below.

Alternately, the Android.Net Xamarin code could be used to construct a NetworkInterface.

$ ifconfig
radio0    Link encap:UNSPEC
          inet addr:192.168.200.2  Bcast:192.168.200.255  Mask:255.255.255.0
          inet6 addr: fec0::34ad:3156:e44c:7fd2/64 Scope: Site
          inet6 addr: fe80::f4dd:7cff:fe8a:7164/64 Scope: Link
          inet6 addr: fec0::f4dd:7cff:fe8a:7164/64 Scope: Site
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:200 errors:0 dropped:0 overruns:0 frame:0
          TX packets:364 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:26233 TX bytes:52801

lo        Link encap:UNSPEC
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope: Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:13 errors:0 dropped:0 overruns:0 frame:0
          TX packets:13 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1
          RX bytes:852 TX bytes:852

wlan0     Link encap:UNSPEC    Driver mac80211_hwsim
          inet addr:192.168.232.2  Bcast:192.168.239.255  Mask:255.255.248.0
          inet6 addr: fe80::15:b2ff:fe00:0/64 Scope: Link
          inet6 addr: fec0::b5b6:cf7:753e:c210/64 Scope: Site
          inet6 addr: fec0::15:b2ff:fe00:0/64 Scope: Site
          UP BROADCAST RUNNING MULTICAST  MTU:1400  Metric:1
          RX packets:168266 errors:0 dropped:0 overruns:0 frame:0
          TX packets:63578 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:106642482 TX bytes:8605743

$ ip route list match 0 table all scope global
default via 192.168.232.1 dev wlan0 table 1003 proto static
default via 192.168.200.1 dev radio0 table 1011 proto static

$ ip route show
192.168.200.0/24 dev radio0 proto kernel scope link src 192.168.200.2
192.168.232.0/21 dev wlan0 proto kernel scope link src 192.168.232.2

$ ip neigh
192.168.200.1 dev radio0 lladdr 9a:79:ee:05:4e:22 STALE
192.168.232.1 dev wlan0 lladdr 02:15:b2:00:01:00 REACHABLE
fe80::15:b2ff:fe00:100 dev wlan0 lladdr 02:15:b2:00:01:00 router STALE
fe80::9879:eeff:fe05:4e22 dev radio0 lladdr 9a:79:ee:05:4e:22 router STALE


Code in MainActivity.cs

using System;
using System.Net.NetworkInformation;
using Android.App;
using Android.OS;
using Android.Runtime;
using Android.Widget;
using Debug = System.Diagnostics.Debug;

namespace Android.GetAllActiveNetworkInterfaces
{
    [Activity(Label = "@string/app_name", MainLauncher = true)]
    public class MainActivity : Activity
    {
        protected override void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);

            try
            {
                foreach (var networkInterface in NetworkInterface.GetAllNetworkInterfaces())
                {
                    var name = networkInterface.Name;
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine("GetAllNetworkInterfaces threw exception: ", ex);
            }

            // Set our view from the "main" layout resource
            SetContentView(Resource.Layout.activity_main);
        }
    }
}

Configuration Information:

DotNet Versions: 6.0.100-preview.7.21379.14
Android: targeting SDK version 30
Microsoft Visual Studio Enterprise 2022 Preview
Version 17.0.0 Preview 3.1
VisualStudio.17.Preview/17.0.0-pre.3.1+31612.314
Microsoft .NET Framework
Version 4.8.04084

Android Manifest:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" 
          android:versionCode="1" 
          android:versionName="1.0" 
          package="com.companyname.Android.GetAllActiveNetworkInterfaces">
  <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="30" />
  <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true">
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.INTERNET" />
  </application>
</manifest>
@dotnet-issue-labeler
Copy link

I couldn't figure out the best area label to add to this issue. If you have write-permissions please help me learn by adding exactly one area label.

@dotnet-issue-labeler dotnet-issue-labeler bot added the untriaged New issue has not been triaged by the area owner label Aug 30, 2021
@ghost
Copy link

ghost commented Aug 30, 2021

Tagging subscribers to this area: @dotnet/ncl
See info in area-owners.md if you want to be subscribed.

Issue Details

Steps To Reproduce:

  1. Dotnet new android
  2. Add to csproj so LaunchProfiles start up
  <PropertyGroup>
    <_KeepLaunchProfiles>true</_KeepLaunchProfiles>
  </PropertyGroup>
  1. Modify MainActivity.cs by adding the following code.
  2. Build and Run in Visual Studio 17.0.0 Preview 3.1

Result:

An exception is thrown and is null

Expected:

  • No exception and results of NetworkInterface.GetAllNetworkInterfaces to be returned.

Related to System.Net.NetworkInformation needs Android PAL #51303
The System.Net.NetworkInformation APIs stopped working on Android. I have provided a simple repo. This is related to issue System.Net.NetworkInformation needs Android PAL #51303.

In the code below, a null exception is thrown. I have also seen the following exception in another project:
NetworkInformation.NetworkInformationException : No such file or directory

Suggestions:

I'm writing a mobile and desktop networking application so it would be helpful for the System.NetworkInterface APIs to work cross platform. Android stopped providing direct access to the system files in API level 24.

However, Android includes the ip and ifconfig commands which essentially read the contents of these protected system files and could be used to create a NetworkInterface on Android. See output below.

Alternately, the Android.Net Xamarin code could be used to construct a NetworkInterface.

$ ifconfig
radio0    Link encap:UNSPEC
          inet addr:192.168.200.2  Bcast:192.168.200.255  Mask:255.255.255.0
          inet6 addr: fec0::34ad:3156:e44c:7fd2/64 Scope: Site
          inet6 addr: fe80::f4dd:7cff:fe8a:7164/64 Scope: Link
          inet6 addr: fec0::f4dd:7cff:fe8a:7164/64 Scope: Site
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:200 errors:0 dropped:0 overruns:0 frame:0
          TX packets:364 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:26233 TX bytes:52801

lo        Link encap:UNSPEC
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope: Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:13 errors:0 dropped:0 overruns:0 frame:0
          TX packets:13 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1
          RX bytes:852 TX bytes:852

wlan0     Link encap:UNSPEC    Driver mac80211_hwsim
          inet addr:192.168.232.2  Bcast:192.168.239.255  Mask:255.255.248.0
          inet6 addr: fe80::15:b2ff:fe00:0/64 Scope: Link
          inet6 addr: fec0::b5b6:cf7:753e:c210/64 Scope: Site
          inet6 addr: fec0::15:b2ff:fe00:0/64 Scope: Site
          UP BROADCAST RUNNING MULTICAST  MTU:1400  Metric:1
          RX packets:168266 errors:0 dropped:0 overruns:0 frame:0
          TX packets:63578 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:106642482 TX bytes:8605743

$ ip route list match 0 table all scope global
default via 192.168.232.1 dev wlan0 table 1003 proto static
default via 192.168.200.1 dev radio0 table 1011 proto static

$ ip route show
192.168.200.0/24 dev radio0 proto kernel scope link src 192.168.200.2
192.168.232.0/21 dev wlan0 proto kernel scope link src 192.168.232.2

$ ip neigh
192.168.200.1 dev radio0 lladdr 9a:79:ee:05:4e:22 STALE
192.168.232.1 dev wlan0 lladdr 02:15:b2:00:01:00 REACHABLE
fe80::15:b2ff:fe00:100 dev wlan0 lladdr 02:15:b2:00:01:00 router STALE
fe80::9879:eeff:fe05:4e22 dev radio0 lladdr 9a:79:ee:05:4e:22 router STALE


Code in MainActivity.cs

using System;
using System.Net.NetworkInformation;
using Android.App;
using Android.OS;
using Android.Runtime;
using Android.Widget;
using Debug = System.Diagnostics.Debug;

namespace Android.GetAllActiveNetworkInterfaces
{
    [Activity(Label = "@string/app_name", MainLauncher = true)]
    public class MainActivity : Activity
    {
        protected override void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);

            try
            {
                foreach (var networkInterface in NetworkInterface.GetAllNetworkInterfaces())
                {
                    var name = networkInterface.Name;
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine("GetAllNetworkInterfaces threw exception: ", ex);
            }

            // Set our view from the "main" layout resource
            SetContentView(Resource.Layout.activity_main);
        }
    }
}

Configuration Information:

DotNet Versions: 6.0.100-preview.7.21379.14
Android: targeting SDK version 30
Microsoft Visual Studio Enterprise 2022 Preview
Version 17.0.0 Preview 3.1
VisualStudio.17.Preview/17.0.0-pre.3.1+31612.314
Microsoft .NET Framework
Version 4.8.04084

Android Manifest:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" 
          android:versionCode="1" 
          android:versionName="1.0" 
          package="com.companyname.Android.GetAllActiveNetworkInterfaces">
  <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="30" />
  <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true">
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.INTERNET" />
  </application>
</manifest>
Author: SteveBush
Assignees: -
Labels:

area-System.Net, os-android, untriaged

Milestone: -

@marek-safar marek-safar added this to the 7.0.0 milestone Sep 1, 2021
@marek-safar marek-safar removed the untriaged New issue has not been triaged by the area owner label Sep 1, 2021
@marek-safar
Copy link
Contributor

@steveisok I think it'd make sense to change the exception to PNSE

@SteveBush
Copy link
Author

The NetworkInformation class works in Xamarin.Android. By not supporting it in net6.0-android, all of the NuGet packages which use the NetworkInformation would be unavailable on .net60. While I can create an abstraction layer for my code, I use some Nuget packages which no longer work if I compile for net6.0-android.

From what I can see from the code, it looks like the Android implementation of NetworkInformation uses the Linux PAL to call the native method getifaddrs(). In the Xamarin.Android, project there is a native implementation of getifaddrs() for Android.

https://github.com/xamarin/xamarin-android/blob/main/src/monodroid/jni/xamarin_getifaddrs.cc

For my purposes, I have created an abstraction layer for NetworkInformation that uses the ip link command to generate a list of network interfaces. I parse the output of ip link to implement NetworkInformation.GetAllNetworkInterfaces.

Below is the output from the ip link command.

generic_x86_arm:/ $ ip link
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
3: wlan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1400 qdisc mq state UP mode DORMANT group default qlen 1000
    link/ether 02:15:b2:00:00:00 brd ff:ff:ff:ff:ff:ff
6: ip_vti0@NONE: <NOARP> mtu 1364 qdisc noop state DOWN mode DEFAULT group default qlen 1
    link/ipip 0.0.0.0 brd 0.0.0.0
7: ip6_vti0@NONE: <NOARP> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1
    link/tunnel6 :: brd ::
8: sit0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN mode DEFAULT group default qlen 1
    link/sit 0.0.0.0 brd 0.0.0.0
9: ip6tnl0@NONE: <NOARP> mtu 1452 qdisc noop state DOWN mode DEFAULT group default qlen 1
    link/tunnel6 :: brd ::
11: radio0@if10: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000
    link/ether 42:b4:98:b4:16:71 brd ff:ff:ff:ff:ff:ff link-netnsid 0
generic_x86_arm:/ $

@wfurt
Copy link
Member

wfurt commented Sep 13, 2021

I was thinking about the Netlink even for Linux and some other parts - like getting routes. I'm not sure about Andrioind user but on Linux GetAllActiveNetworkInterfaces is used quite frequently.

@SteveBush
Copy link
Author

Unfortunately, none of the solutions I proposed above work in API, level 31. The ip commands work fine on a simulator but fail on a device starting in API, level 31. Most of the networking APIs were deprecated in API level 29.

https://developer.android.com/reference/android/net/ConnectivityManager#getAllNetworkInfo()

getAllNetworks was deprecated in Level 31.

public Network[] getAllNetworks ()
This method was deprecated in API level 31.
This method does not provide any notification of network state changes, forcing apps to call it repeatedly. This is inefficient and prone to race conditions. Apps should use methods such as registerNetworkCallback(android.net.NetworkRequest, android.net.ConnectivityManager.NetworkCallback) instead. Apps that desire to obtain information about networks that do not apply to them can use NetworkRequest.Builder#setIncludeOtherUidNetworks.

The best option would be to use the Xamarin native implementation of getifaddrs().

@I4-PJ
Copy link

I4-PJ commented Sep 30, 2021

Hello, I have (maybe similar issue) with NetworkInterface.GetAllNetworkInterfaces() under Android. When executing the method I am getting "System.Net.NetworkInformation.NetworkInformationException: 'Success'" exception instead of returing expected values.

the exception is thrown within static method at this line:
var interf = NetworkInterface.GetAllNetworkInterfaces();

Application min. API is 27, target API 31. / NET6 rc1

PJ.

@ghost ghost added the in-pr There is an active PR which will close this issue when it is merged label Jan 11, 2022
@ghost ghost removed the in-pr There is an active PR which will close this issue when it is merged label Jan 13, 2022
@ghost ghost locked as resolved and limited conversation to collaborators Feb 12, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants