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

the socket module should include getifaddrs because it is necessary to translate the output of if_nameindex into addresses #126713

Open
glyph opened this issue Nov 12, 2024 · 5 comments
Labels
type-feature A feature request or enhancement

Comments

@glyph
Copy link
Contributor

glyph commented Nov 12, 2024

Feature or enhancement

Proposal:

socket.if_nameindex, socket.if_nametoindex and socket.if_indextoname all work in terms of interface names and indexes. But in order to do much of use with these values, you need to know what addresses they have, and as far as I can tell the socket module does not provide a means to do so.

This function exists in psutil, in netifaces, and there are various recipes lying around on Stack Overflow and elsewhere for accessing this function.

Has this already been discussed elsewhere?

This is a minor feature, which does not need previous discussion elsewhere

Links to previous discussion of this feature:

No response

@glyph glyph added the type-feature A feature request or enhancement label Nov 12, 2024
@Zheaoli
Copy link
Contributor

Zheaoli commented Nov 12, 2024

I am not sure the scenario you are working for. Would you mind providing more information about the API you want?

@glyph
Copy link
Contributor Author

glyph commented Nov 12, 2024

This is more of a general completeness issue than a specific scenario. Any time that you need to select a network interface, the user may know it under its address (but the application needs to know its name) or under its name (but the application needs to know its address). However, I will describe the specific scenario that lead me to discover it.

On a multicast socket, the sending interface is described in IPv4 as a packed address, same as the interface, via the IPPROTO_IP / IP_MULTICAST_IF socket option. However, when adding IPv6 support, and using the IPV6_MULTICAST_IF option, the sending interface must be specified via an integer interface index, such as those returned by if_nameindex.

There are no standard names for interfaces; for a notable example, BSDs tend to use lo0 for localhost and Linux tends to use lo. Therefore, when writing tests that want to bind multicast to a local interface, properly identifying such an interface involves identifying it via its addresses, which are standardized (127.0.0.1, ::1) as opposed to its name or index which are not. There is no facility in the python standard library to do this.

In terms of what API is required, it's basically just this: https://github.com/twisted/twisted/blob/f10c1cf5548edf410e1a07620817f5f0aa291afe/src/twisted/internet/test/_posixifaces.py#L31-L155

On Windows, I think Win32_NetworkAdapterConfiguration provides similar information.

@Zheaoli
Copy link
Contributor

Zheaoli commented Nov 12, 2024

I think your idea is making sense. We need a api provide full interface info like psutil do

In [2]: psutil.net_if_addrs()
Out[2]:
{'lo': [snicaddr(family=<AddressFamily.AF_INET: 2>, address='127.0.0.1', netmask='255.0.0.0', broadcast=None, ptp=None),
  snicaddr(family=<AddressFamily.AF_INET6: 10>, address='::1', netmask='ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff', broadcast=None, ptp=None),
  snicaddr(family=<AddressFamily.AF_PACKET: 17>, address='00:00:00:00:00:00', netmask=None, broadcast=None, ptp=None)],
 'enp8s0': [snicaddr(family=<AddressFamily.AF_INET: 2>, address='192.168.0.239', netmask='255.255.0.0', broadcast='192.168.255.255', ptp=None),
  snicaddr(family=<AddressFamily.AF_INET6: 10>, address='fd7d:f44c:60a5:bb4e:a299:6d2e:a177:ed81', netmask='ffff:ffff:ffff:ffff::', broadcast=None, ptp=None),
  snicaddr(family=<AddressFamily.AF_INET6: 10>, address='fe80::985:d7ff:aec8:fc23%enp8s0', netmask='ffff:ffff:ffff:ffff::', broadcast=None, ptp=None),
  snicaddr(family=<AddressFamily.AF_PACKET: 17>, address='50:eb:f6:ee:58:99', netmask=None, broadcast='ff:ff:ff:ff:ff:ff', ptp=None)],
 'docker0': [snicaddr(family=<AddressFamily.AF_INET: 2>, address='172.90.0.1', netmask='255.255.255.0', broadcast='172.90.0.255', ptp=None),
  snicaddr(family=<AddressFamily.AF_INET6: 10>, address='fe80::42:3dff:fe98:a84b%docker0', netmask='ffff:ffff:ffff:ffff::', broadcast=None, ptp=None),
  snicaddr(family=<AddressFamily.AF_PACKET: 17>, address='02:42:3d:98:a8:4b', netmask=None, broadcast='ff:ff:ff:ff:ff:ff', ptp=None)],
 'br-d80b8a2f8fa2': [snicaddr(family=<AddressFamily.AF_INET: 2>, address='172.17.0.1', netmask='255.255.0.0', broadcast='172.17.255.255', ptp=None),
  snicaddr(family=<AddressFamily.AF_PACKET: 17>, address='02:42:93:c0:d7:76', netmask=None, broadcast='ff:ff:ff:ff:ff:ff', ptp=None)],
 'vethf9adaf5': [snicaddr(family=<AddressFamily.AF_INET6: 10>, address='fe80::7423:5ff:fef7:78f6%vethf9adaf5', netmask='ffff:ffff:ffff:ffff::', broadcast=None, ptp=None),
  snicaddr(family=<AddressFamily.AF_PACKET: 17>, address='76:23:05:f7:78:f6', netmask=None, broadcast='ff:ff:ff:ff:ff:ff', ptp=None)],
 'wlo1': [snicaddr(family=<AddressFamily.AF_PACKET: 17>, address='1e:f0:f0:f7:84:9b', netmask=None, broadcast='ff:ff:ff:ff:ff:ff', ptp=None)]}

@Zheaoli
Copy link
Contributor

Zheaoli commented Nov 12, 2024

I think we need a core dev's idea to review this idea before we design the API. I think it makes sense to add a new API .

WDYT @giampaolo ?

@glyph
Copy link
Contributor Author

glyph commented Nov 12, 2024

I think it makes sense to add a new API .

Agreed; I think the stdlib's scope should just be to wrap the platform API minimally, and not to get too fancy with abstracting it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type-feature A feature request or enhancement
Projects
None yet
Development

No branches or pull requests

2 participants