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

Adding uv_interfaces to retrieve the complete list of interfaces. #158

Open
zenoamaro opened this issue Jan 23, 2015 · 20 comments
Open

Adding uv_interfaces to retrieve the complete list of interfaces. #158

zenoamaro opened this issue Jan 23, 2015 · 20 comments

Comments

@zenoamaro
Copy link

Currently libuv provides a list of all addresses assigned to network interfaces on uv_interface_addresses, but this is limited to up and running interfaces having inet addresses, and as such there's no way to recover a full list of interfaces from it. This would benefit users like node, and in fact follows from nodejs/node#498.

I'm proposing the addition of uv_interfaces (and uv_free_interfaces), implemented similarly to uv_interface_addresses, returning a list of all visible interfaces, with or without link-level details depending on the platform, but without the addresses. I'd submit a PR for this myself, but as this would be an API change I'm waiting to hear what's the opinion on this change.

Also, implementing this on linux and bsds should be quite straightforward, but I'm not equally accustomed to the other platforms, so it would be great if someone could chime in with possible cross-platform concerns.

@saghul
Copy link
Member

saghul commented Jan 23, 2015

The functionality of both looks too close not to try to unify them. How about this:

  • uv_net_interfaces (or any other better name) becomes the "new" API, which lists all interfaces, and if they are down, the address is not set (we set the family to AF_UNSPEC).
  • uv_interface_addresses becomes deprecated in v1.x, scheduled for removal on v2.x.

Now, as @bnoordhuis pointed out in nodejs/node#498 the patch will be tedious because it has to be implemented for every Unix system we support, ideally without a ton of code duplication. It shouldn't be too hard though.

@zenoamaro
Copy link
Author

Some thoughts about the interface for this:

  • I think it's fine to skip over X25, IPX etc. and restrict to eth/ip interfaces (inb4 uv_actually_all_interfaces).

  • We return at least one AF_LINK address for each interface, containing the physical address, and that would be the only result for interfaces without AF_INET* addresses. OR, we return the physical address with every inet address, but only the physical address for those without addresses.

  • We can return one AF_UNSPEC for entries with a NULL address pointer (tun0 is an usual suspect on linux/bsd as it does not have a link-layer address), but we probably should skip those entirely.

  • To put the cherry on top of it and make the definitive interface we could also return the broadcast address, and common portable flags such as broadcast or multicast capability. We would need a new data type though, something like this maybe?:

    typedef struct uv_net_interfaces_s {
        char* name;
    
        // Look 
        int is_up_and_running;
        int is_loopback;
        int is_point_to_point;
        int is_promiscuous;
        int has_broadcast;
        int has_multicast;
    
        // NULL unless link layer
        // We could use sockaddr_dl here.
        char phys_addr[8]; // Enough to store a firewire address.
        int phys_addr_len;
    
        // NULL unless inet
        union {
            struct sockaddr_in address4;
            struct sockaddr_in6 address6;
        } address;
    
        // NULL unless inet
        union {
            struct sockaddr_in broadcast4;
            struct sockaddr_in6 broadcast6;
        } broadcast;
    
        // NULL unless inet
        union {
            struct sockaddr_in netmask4;
            struct sockaddr_in6 netmask6;
        } netmask;
    
    } uv_net_interfaces_t;

@txdv
Copy link
Contributor

txdv commented Jan 27, 2015

Is libuv becomming a custom glibc implementation?

@zenoamaro
Copy link
Author

@txdv, it's basically the same as it is now, minus some filtering and plus a few fields.

@txdv
Copy link
Contributor

txdv commented Jan 27, 2015

I was just kidding ;)

@zenoamaro
Copy link
Author

It would be a valid concern, though. I'm trying to avoid just stuffing all of ifaddrs inside it.

@bnoordhuis
Copy link
Member

I think I'm in favor of the suggested API.

@saghul
Copy link
Member

saghul commented Jan 28, 2015

Some thoughts about the interface for this:

I think it's fine to skip over X25, IPX etc. and restrict to eth/ip interfaces (inb4 uv_actually_all_interfaces).

Yeah.

We return at least one AF_LINK address for each interface, containing the physical address, and that would be the only result for interfaces without AF_INET* addresses. OR, we return the physical address with every inet address, but only the physical address for those without addresses.

We currently have the physical address for all interfaces. It would be nice to keep that. Currently we don't have a phys_addr_len field, is it needed? Is there any physical address which has embedded nulls?

We can return one AF_UNSPEC for entries with a NULL address pointer (tun0 is an usual suspect on linux/bsd as it does not have a link-layer address), but we probably should skip those entirely.

But tun interfaces do have an IP address, can't we get that? Either way, if there is no AF_INET/6 address we can just set the family to AF_UNSPEC.

To put the cherry on top of it and make the definitive interface we could also return the broadcast address, and common portable flags such as broadcast or multicast capability. We would need a new data type though, something like this maybe?:

Yeah, looks good! (look at my comments from above).

Now, what libuv version should we be targetting?

@zenoamaro
Copy link
Author

We currently have the physical address for all interfaces. It would be nice to keep that.

I'm fine with that, even though it kinda feels redundant.

Currently we don't have a phys_addr_len field, is it needed? Is there any physical address which has embedded nulls?

Firewire devices would end up included in the output now (as regular ip devices), and they have 8 bytes of physical address. This is how sockaddr_ll and IP_ADAPTER_ADDRESSES specify them. Right now we are either nulling it or cutting it if it isn't six bytes, which is awful.

But tun interfaces do have an IP address, can't we get that?

We can, it's just that they have a NULL ifa_addr pointer instead of the usual AF_PACKET/AF_LINK as first interface, which means don't have a physical address for those.

Anyway, I'll draft a pull request with an initial implementation, and some tests, and we'll see where that takes us.

@saghul
Copy link
Member

saghul commented Jan 28, 2015

Firewire devices would end up included in the output now (as regular ip devices), and they have 8 bytes of physical address. This is how sockaddr_ll and IP_ADAPTER_ADDRESSES specify them. Right now we are either nulling it or cutting it if it isn't six bytes, which is awful.

Yeah. My point is that we don't really nee dthe length if we null terminate the buffer properly, do we?

We can, it's just that they have a NULL ifa_addr pointer instead of the usual AF_PACKET/AF_LINK as first interface, which means don't have a physical address for those.

That's fine.

Anyway, I'll draft a pull request with an initial implementation, and some tests, and we'll see where that takes us.

Sure!

@zenoamaro
Copy link
Author

My point is that we don't really nee dthe length if we null terminate the buffer properly, do we?

How would we store an address like 0a:00:27:00:00:00 (vboxnet on my machine)? Even if we zero the field and have the user take the correct slice from it, there's no way AFAIK for him to know how many bytes that interface uses (6 or 8 currently). The only other way I can think of is storing it as an ascii string, but that'd be really inconvenient. Am I missing something?

@saghul
Copy link
Member

saghul commented Jan 28, 2015

Gotcha, go ahead with the length :-)

@zenoamaro
Copy link
Author

Well, to be honest I don't like this solution very much too. I'd rather use a standard sockaddr_ll but unfortunately we don't have that neither on windows nor on mac.

@pprindeville
Copy link

We can return one AF_UNSPEC for entries with a NULL address pointer (tun0 is an usual suspect on linux/bsd as it does not have a link-layer address), but we probably should skip those entirely.

@zenoamaro I agree with @saghul that just because tun interfaces don't have layer 2 addresses doesn't mean the layer 3 information isn't useful.

@stale
Copy link

stale bot commented Aug 10, 2019

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the stale label Aug 10, 2019
@stale stale bot closed this as completed Aug 17, 2019
@pprindeville
Copy link

BTW, IPsec, IP-in-IP and GRE tunnels would only ever have a layer 3 address, since they are software abstractions at the IP layer.

@pprindeville
Copy link

Can we get this reopened? It looked like we had consensus on the API.

@santigimeno santigimeno reopened this Dec 29, 2021
@stale stale bot removed the stale label Dec 29, 2021
@stale
Copy link

stale bot commented Apr 16, 2022

This issue has been automatically marked as stale because it has not had recent activity. Thank you for your contributions.

@stale stale bot added the stale label Apr 16, 2022
@calvin2021y
Copy link

almost 8 year passed, any progress?

@stale stale bot removed the stale label Feb 1, 2023
@bnoordhuis
Copy link
Member

Yes, actually. #2033 (broadcast address) was merged to the master branch two weeks ago. Everything else is still up for grabs.

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

Successfully merging a pull request may close this issue.

7 participants