Runtime: NetworkInterface's GatewayAddresses property not returning IPv6 gateway address on Linux

Created on 8 Mar 2019  路  10Comments  路  Source: dotnet/runtime

I was trying to send a TCP message over IPv6 from a docker container to its host machine by using the docker network鈥檚 gateway IP address. In the docker module, we are using .NET core鈥檚 (2.1) NetworkInterface type and grabbing the GatewayAddresses property from the network interface鈥檚 IP properties to fetch the IP address of the gateway. Unfortunately, that only returns the IPv4 address of the gateway and not the IPv6 address even though it exists.

It appears that the Gateway addresses property only returns the addresses by looking at the IPv4 network route file ("/proc/net/route") in Linux and not IPv6 ("/proc/net/ipv6_route"):

https://github.com/dotnet/corefx/blob/a8cef502cd74aabb209cb9ad7a1e2a5bc1612459/src/System.Net.NetworkInformation/src/System/Net/NetworkInformation/LinuxIPInterfaceProperties.cs#L49-L56

Can we change it so that both IPv4 and IPv6 addresses of the gateway are returned?

area-System.Net bug os-linux

Most helpful comment

When you look at documentation: https://docs.microsoft.com/en-us/dotnet/api/system.net.networkinformation.ipinterfaceproperties.gatewayaddresses?view=netcore-2.2
it clearly states this property returns IPv4 address. Expecting IPv6 is clearly misunderstanding.
In case of dual stack with IPv4/IPv6 there is no way how we can return both. This API was clearly designed before dual stack become common.

We do not need a new API for this. The current documentation is wrong. The documentation needs to be fixed.

If you run the following code on .NET Framework or .NET Core (Windows), it will return both IPv4 and IPv6 addresses:

```c#
public static void DisplayGatewayAddresses()
{
NetworkInterface[] adapters = NetworkInterface.GetAllNetworkInterfaces();
foreach (NetworkInterface adapter in adapters)
{
IPInterfaceProperties adapterProperties = adapter.GetIPProperties();
GatewayIPAddressInformationCollection gateways = adapterProperties.GatewayAddresses;
foreach (GatewayIPAddressInformation gateway in gateways)
{
Console.WriteLine($"Gateway Address: {gateway.Address.ToString()}");
}
}
}


example output:

Gateway Address: fe80::200:5eff:fe00:221%7
Gateway Address: 10.127.72.1


We have other APIs in the System.Net.NetworkInformation namespace that also provide both IPv4 and IPv6 addresses.

```c#
public static void DisplayDnsAddresses()
{
    NetworkInterface[] adapters = NetworkInterface.GetAllNetworkInterfaces();
    foreach (NetworkInterface adapter in adapters)
    {
        IPInterfaceProperties adapterProperties = adapter.GetIPProperties();
        IPAddressCollection dnsServers = adapterProperties.DnsAddresses;
        if (dnsServers.Count > 0)
        {
            Console.WriteLine(adapter.Description);
            foreach (IPAddress dns in dnsServers)
            {
                Console.WriteLine("  DNS Servers ............................. : {0}",
                    dns.ToString());
            }
            Console.WriteLine();
        }
    }
}

example output:

Hyper-V Virtual Ethernet Adapter dotnet/corefx#2
  DNS Servers ............................. : fec0:0:0:ffff::1%1
  DNS Servers ............................. : fec0:0:0:ffff::2%1
  DNS Servers ............................. : fec0:0:0:ffff::3%1

Intel(R) 82579LM Gigabit Network Connection
  DNS Servers ............................. : 10.50.10.50
  DNS Servers ............................. : 10.50.50.50

Npcap Loopback Adapter
  DNS Servers ............................. : fec0:0:0:ffff::1%1
  DNS Servers ............................. : fec0:0:0:ffff::2%1
  DNS Servers ............................. : fec0:0:0:ffff::3%1

Software Loopback Interface 1
  DNS Servers ............................. : fec0:0:0:ffff::1%1
  DNS Servers ............................. : fec0:0:0:ffff::2%1
  DNS Servers ............................. : fec0:0:0:ffff::3%1

Hyper-V Virtual Ethernet Adapter
  DNS Servers ............................. : fec0:0:0:ffff::1%1
  DNS Servers ............................. : fec0:0:0:ffff::2%1
  DNS Servers ............................. : fec0:0:0:ffff::3%1

This issue on Linux is a bug in .NET Core and doesn't need new APIs.

All 10 comments

@wfurt

can you post repro code @shantanu1singh? THis may be even trickier as we read info from /proc and that may or may not work for networking within container.

Moving to 3.0 as it will block IoT scenarios.

When you look at documentation: https://docs.microsoft.com/en-us/dotnet/api/system.net.networkinformation.ipinterfaceproperties.gatewayaddresses?view=netcore-2.2

it clearly states this property returns IPv4 address. Expecting IPv6 is clearly misunderstanding.
In case of dual stack with IPv4/IPv6 there is no way how we can return both. This API was clearly designed before dual stack become common.

I understand that only IPv4 addresses are returned by this property as per the documentation but we would like to have a way to retrieve the IPv6 Address too whether it be a different property (or some other mechanism).

What exactly are you trying to achieve? Get IPv6 default gateway in case one is set?
I would assume this is somewhat rare operation when system starts?
Do you expect this to change through out live of the application?
I can look for some suggestions but it would help me to understand what the use case is.

We're trying to get the IPv6 address of the default gateway from within a container so that we can communicate with the host (of the container) over TCP/IP (some port). This isn't intended to be a rare operation, we might want to use it several times during the container's lifetime. The address could be dynamic in nature too.

We can look at adding some API to 3.0. NetworkInterface seems strange place as routes are not tight to interface. This may come from simplistic view with one NIC and only default gateway.
Routing in general can be more complicated, certainly on Linux.

In mean time, you can use something like the fragment bellow. I tested that with Docker on ARM64 system. It return first IPv6 default route or null and it will work with 2.x as well as 3.x

``` c#
using System;
using System.Net;
using System.IO;

namespace Test
{
class Program
{
private static int HexToInt(char val)
{
if (val <= '9' && val >= '0')
{
return (val - '0');
}
else if (val >= 'a' && val <= 'f')
{
return ((val - 'a') + 10);
}
else if (val >= 'A' && val <= 'F')
{
return ((val - 'A') + 10);
}
else
{
throw new InvalidDataException(val.ToString());
}
}

    static IPAddress GetV6Gw()
    {
        IPAddress gw = null;
        using (StreamReader sr =  File.OpenText("/proc/net/ipv6_route"))
        {
            string line;
            do {
                line = sr.ReadLine();
                if (line != null && line.StartsWith("00000000000000000000000000000000"))
                {
                    String[] token = line.Split();
                    if (token.Length > 4 && token[4] != "00000000000000000000000000000000")
                    {
                        byte[] addressBytes = new byte[16];
                        for (int i = 0; i < 16; i++)
                        {
                            addressBytes[i] = (byte)(HexToInt(token[4][(i * 2)]) * 16
                                                   + HexToInt(token[4][(i * 2) + 1]));
                        }

                        return new IPAddress(addressBytes);
                    }
                }
            } while (line != null);
        }

        return  gw;
    }

    static void Main(string[] args)
    {
        Console.WriteLine("Hello World! {0}", GetV6Gw());
    }
}

}
```

When you look at documentation: https://docs.microsoft.com/en-us/dotnet/api/system.net.networkinformation.ipinterfaceproperties.gatewayaddresses?view=netcore-2.2
it clearly states this property returns IPv4 address. Expecting IPv6 is clearly misunderstanding.
In case of dual stack with IPv4/IPv6 there is no way how we can return both. This API was clearly designed before dual stack become common.

We do not need a new API for this. The current documentation is wrong. The documentation needs to be fixed.

If you run the following code on .NET Framework or .NET Core (Windows), it will return both IPv4 and IPv6 addresses:

```c#
public static void DisplayGatewayAddresses()
{
NetworkInterface[] adapters = NetworkInterface.GetAllNetworkInterfaces();
foreach (NetworkInterface adapter in adapters)
{
IPInterfaceProperties adapterProperties = adapter.GetIPProperties();
GatewayIPAddressInformationCollection gateways = adapterProperties.GatewayAddresses;
foreach (GatewayIPAddressInformation gateway in gateways)
{
Console.WriteLine($"Gateway Address: {gateway.Address.ToString()}");
}
}
}


example output:

Gateway Address: fe80::200:5eff:fe00:221%7
Gateway Address: 10.127.72.1


We have other APIs in the System.Net.NetworkInformation namespace that also provide both IPv4 and IPv6 addresses.

```c#
public static void DisplayDnsAddresses()
{
    NetworkInterface[] adapters = NetworkInterface.GetAllNetworkInterfaces();
    foreach (NetworkInterface adapter in adapters)
    {
        IPInterfaceProperties adapterProperties = adapter.GetIPProperties();
        IPAddressCollection dnsServers = adapterProperties.DnsAddresses;
        if (dnsServers.Count > 0)
        {
            Console.WriteLine(adapter.Description);
            foreach (IPAddress dns in dnsServers)
            {
                Console.WriteLine("  DNS Servers ............................. : {0}",
                    dns.ToString());
            }
            Console.WriteLine();
        }
    }
}

example output:

Hyper-V Virtual Ethernet Adapter dotnet/corefx#2
  DNS Servers ............................. : fec0:0:0:ffff::1%1
  DNS Servers ............................. : fec0:0:0:ffff::2%1
  DNS Servers ............................. : fec0:0:0:ffff::3%1

Intel(R) 82579LM Gigabit Network Connection
  DNS Servers ............................. : 10.50.10.50
  DNS Servers ............................. : 10.50.50.50

Npcap Loopback Adapter
  DNS Servers ............................. : fec0:0:0:ffff::1%1
  DNS Servers ............................. : fec0:0:0:ffff::2%1
  DNS Servers ............................. : fec0:0:0:ffff::3%1

Software Loopback Interface 1
  DNS Servers ............................. : fec0:0:0:ffff::1%1
  DNS Servers ............................. : fec0:0:0:ffff::2%1
  DNS Servers ............................. : fec0:0:0:ffff::3%1

Hyper-V Virtual Ethernet Adapter
  DNS Servers ............................. : fec0:0:0:ffff::1%1
  DNS Servers ............................. : fec0:0:0:ffff::2%1
  DNS Servers ............................. : fec0:0:0:ffff::3%1

This issue on Linux is a bug in .NET Core and doesn't need new APIs.

fixed by dotnet/corefx#37132

Was this page helpful?
0 / 5 - 0 ratings