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

Get all local IP addresses doesn't work using System.Net.DNS.GetHostAddresses #5387

Closed
sipsorcery opened this issue Jun 11, 2020 · 5 comments
Labels

Comments

@sipsorcery
Copy link

Environment

Windows build number: Microsoft Windows [Version 10.0.19041.172]
Your Distribution version: Release:        18.04
Whether the issue is on WSL 2 and/or WSL 1: Linux version 4.4.0-19041-Microsoft (Microsoft@Microsoft.com) (gcc version 5.4.0 (GCC) ) #1-Microsoft Fri Dec 06 14:06:00 PST 2019

Steps to reproduce

Minimal .Net Core project to demonstrate the problem:

using System;
using System.Net;

namespace GetLocalIPAddresses
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Get Local IP Addresses Test:");

            var addresses = Dns.GetHostAddresses(string.Empty);
            Console.WriteLine($"Address count {addresses?.Length}.");

            foreach(var address in addresses)
            {
                Console.WriteLine(address);
            }
        }
    }
}

Expected behavior

Based on documentation here a call to System.Net.DNS.GetHostAddresses with an empty string should return a list of all the local IP addresses.

Windows 10 cmd shell result

>dotnet run --framework netcoreapp3.1
Get Local IP Addresses Test:
Address count 6.
fe80::54a9:d238:b2ee:ceb%21
fe80::3c8d:dbf7:1710:efb4%64
fe80::64dc:7955:ef80:6bc4%33
192.168.11.50
172.29.0.1
172.31.32.1

Ubuntu 18.04.4 LTS vm result

$ dotnet run --framework netcoreapp3.1
Get Local IP Addresses Test:
Address count 2.
192.168.11.41
fe80::20c:29ff:fee7:4ce4

Actual behavior

wsl2 result

$ dotnet run --framework netcoreapp3.1
Get Local IP Addresses Test:
Address count 1.
127.0.1.1
$ ifconfig
ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.11.50  netmask 255.255.255.0  broadcast 192.168.11.255
        inet6 fe80::54a9:d238:b2ee:ceb  prefixlen 64  scopeid 0xfd<compat,link,site,host>
        ether c8:d3:ff:b7:83:26  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

eth3: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.31.32.1  netmask 255.255.240.0  broadcast 172.31.47.255
        inet6 fe80::64dc:7955:ef80:6bc4  prefixlen 64  scopeid 0xfd<compat,link,site,host>
        ether 00:15:5d:7a:f6:49  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

eth4: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.29.0.1  netmask 255.255.240.0  broadcast 172.29.15.255
        inet6 fe80::3c8d:dbf7:1710:efb4  prefixlen 64  scopeid 0xfd<compat,link,site,host>
        ether 00:15:5d:58:a3:2e  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 1500
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0xfe<compat,link,site,host>
        loop  (Local Loopback)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
@therealkenc
Copy link
Collaborator

You are going to get way (way) better eyeballs here or similar.

There is no WSL2 actionable: WSL is faithfully executing the syscalls that your program via dotnet is giving the kernel. WSL2 also faithfully executes the syscalls ifconfig gives it. But the two thing have different semantics. [To the extent that Dns.GetHostAddresses(string.Empty) ought have the same semantics as an ifconfig (that might, or genuinely might not, be the case) but either way there is no WSL2 actionable to change the semantics of that function.]

For what it is worth, I did take a short run at it on WSL2 out of pure academic curiosity but my first guess at why you only get localhost back from the function was either wrong or incomplete. Not going to dive to the donet core source to find out, but someone super motivated could at their leisure.

Missing strace(1) log here since I took the trouble do one.

@sipsorcery
Copy link
Author

Thanks for taking a look and verifying it's not a WSL issue. I'll log the issue on dotnet/runtime. Unfortunately that repo seems a bit overwhelmed at the moment with 5k+ issues and previously logged issues are gathering dust.

@therealkenc
Copy link
Collaborator

therealkenc commented Jun 12, 2020

The better command-line analogy than ifconfig is nslookup. For me:

image

There are a lot of moving parts behind that one-liner, including WSL's DNS server (the address in /etc/resolv.conf). So the ask over in the dotnet crowd might be: "be more like nslookup".

That said, I am feeling uncomfortable just punting this. The dotnet peeps are probably going to say something like "dude that's what gethostbyname(3) returns don't look at me". And they wouldn't be wrong.

#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

int main(int argc, char *argv[])
{
    struct hostent *hp = gethostbyname("DESKTOP-QEVBTUT");
    printf("name: %s\n", hp->h_name);
    for (int i = 0; hp->h_addr_list[i] != NULL; i++) {
        struct in_addr *in = (struct in_addr*)hp->h_addr_list[i];
        char *addr = inet_ntoa(*in);
        printf("  %s\n", addr);
    }
}

That yields:

image

Which isn't a very good answer, even if it is the "right" answer according to all the moving pieces as they stand right now. [really late edit, correction] Nah, it is a good answer. That returned 127.0.1.1 is what is typically in a Linux /etc/hosts entry for $HOSTNAME, including on WSL. Which overrules anything DNS has to say on the subject of IP address for $HOSTNAME.

I'll re-open mostly because I've lost my excuse "not going to dive the dotnet source to find out". Maybe there is something WSL could be doing better. No promises you'll get any kind of resolution (joy) in the foreseeable but if I get a chance I'll look a little deeper. I can't tag this WSL bug, because everything is in a sense working properly. But the implication this is some kind of dotnet bug isn't quite right either.

@therealkenc therealkenc reopened this Jun 12, 2020
@sipsorcery
Copy link
Author

The dotnet devs already fixed it dotnet/runtime#27534.

@therealkenc
Copy link
Collaborator

therealkenc commented Jun 12, 2020

Okay fair enough. Thanks for that link. Looks like all I did was retrace the well trodden path over there. If someone else bumps into gethostbyname(3) returning 127.0.1.1 (no one has to date) then that can be done under a different issue cover. [edit] It hasn't come up because that is the correct answer by convention (a salient fact I mistook earlier).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants