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

[Feature]: Support for SO_BINDTODEVICE? #532

Closed
shaunco opened this issue Feb 15, 2024 · 9 comments · Fixed by #650
Closed

[Feature]: Support for SO_BINDTODEVICE? #532

shaunco opened this issue Feb 15, 2024 · 9 comments · Fixed by #650
Assignees
Labels
enhancement New feature or request pending development Requested PR owner to improve code and waiting for the result proposal accepted Proposal has been accepted proposal Proposal for this repo
Milestone

Comments

@shaunco
Copy link

shaunco commented Feb 15, 2024

Description of new feature

While listening for UDP packets, it is common to listen on "0.0.0.0:123" or just ":123", which allows for the receipt of both unicast and broadcast UDP packets, however there are times where an application might want to listen on just a single network interface. Obtaining that interface's IP and then listening on "1.2.3.4:123" will only receive unicast packets, and thus the preferred mechanism is to still listen on ":123" (for v4+v6) or "0.0.0.0:123" (for v4), but to use SO_BINDTODEVICE to bind the socket to a single interface.

Once bound, tools like ss show it as 0.0.0.0%eth0:123 rather than just 0.0.0.0:123.

Scenarios for new feature

On network appliances with multiple interfaces, those interfaces are often attached to different networks - such as a network gateway that is attached to a LAN network on eth0 and the WAN network on eth1. If that device wants to listen for unicast+broadcast UDP on just the LAN interface, there is currently no way to do this with gnet (at least not that I could find).

Breaking changes or not?

No

Code snippets (optional)

For most linux/freebsd based systems:

unix.SetsockoptString(fd, unix.SOL_SOCKET, unix.SO_BINDTODEVICE, a.interfaceName)

For darwin:

iface, _ := net.InterfaceByName(devName)
unix.SetsockoptInt(int(fd), unix.IPPROTO_IP, unix.IP_RECVIF, iface.Index)
unix.SetsockoptInt(int(fd), unix.IPPROTO_IP, unix.IP_BOUND_IF, iface.Index)

For windows, there is example calls at https://stackoverflow.com/a/73041705 , but they'd need to be converted to go.

Alternatives for new feature

Could have separate listeners for unicast and broadcast traffic, but it gets messy.

Could listen to everything and then filter in OnTraffic, but it is much more efficient to have the kernel just bind to a single interface.

Additional context (optional)

WithMulticastInterfaceIndex() does something similar for multicast traffic.

@shaunco shaunco added enhancement New feature or request proposal Proposal for this repo labels Feb 15, 2024
@panjf2000
Copy link
Owner

Sounds reasonable, I'll see what we can do here.

@panjf2000 panjf2000 added pending development Requested PR owner to improve code and waiting for the result proposal accepted Proposal has been accepted labels Feb 19, 2024
@panjf2000
Copy link
Owner

panjf2000 commented Feb 25, 2024

I've done some investigation on this. SO_BINDTODEVICE is linux-specific and it seems that there are no equivalents on other platforms. IP_BOUND_IF seems like a prospective substitute on macOS but it's osx-specific and it doesn't exist on other BSD-like systems.

As for IP_RECVIF on freebsd, it doesn't look like an exact equivalent to SO_BINDTODEVICE according to its man pages.

Therefore, if we're going to do this, it looks like we're only able to do it on linux and mac.

References

@panjf2000 panjf2000 added this to the Long term milestone Feb 25, 2024
@shaunco
Copy link
Author

shaunco commented Mar 10, 2024

Thanks for digging into this. Would that make the functions just NOPs on other platforms or does it imply platform-specific APIs?

@panjf2000
Copy link
Owner

Thanks for digging into this. Would that make the functions just NOPs on other platforms or does it imply platform-specific APIs?

If we're going to do this, API should be present on all platforms that gnet supports and returns an ErrUnsupportedOp.

@panjf2000 panjf2000 modified the milestones: Long term, v2.4 Mar 19, 2024
@panjf2000 panjf2000 modified the milestones: v2.4, Long term, v2.5 Mar 29, 2024
@panjf2000 panjf2000 modified the milestones: v2.5, v2.6 Apr 20, 2024
Copy link

This issue is marked as stale because it has been open for 30 days with no activity.

You should take one of the following actions:

  • Manually close this issue if it is no longer relevant
  • Comment if you have more information to share

This issue will be automatically closed in 7 days if no further activity occurs.

@github-actions github-actions bot added the stale label Sep 26, 2024
@panjf2000 panjf2000 removed the stale label Sep 26, 2024
@shaunco
Copy link
Author

shaunco commented Sep 27, 2024

No more information to share, but still very interested in this functionality.

Copy link

This issue is marked as stale because it has been open for 30 days with no activity.

You should take one of the following actions:

  • Manually close this issue if it is no longer relevant
  • Comment if you have more information to share

This issue will be automatically closed in 7 days if no further activity occurs.

@github-actions github-actions bot added the stale label Oct 28, 2024
@panjf2000
Copy link
Owner

I plan on doing this next month if nothing else gets in the way.

@panjf2000 panjf2000 removed the stale label Oct 28, 2024
panjf2000 added a commit that referenced this issue Nov 8, 2024
panjf2000 added a commit that referenced this issue Nov 8, 2024
panjf2000 added a commit that referenced this issue Nov 8, 2024
panjf2000 added a commit that referenced this issue Nov 8, 2024
panjf2000 added a commit that referenced this issue Nov 8, 2024
panjf2000 added a commit that referenced this issue Nov 8, 2024
panjf2000 added a commit that referenced this issue Nov 8, 2024
panjf2000 added a commit that referenced this issue Nov 8, 2024
@panjf2000
Copy link
Owner

panjf2000 commented Nov 8, 2024

Updated:
The root cause should have been the loopback interface which doesn't normally receive broadcast packets. I might need to test it on "eth0".


After some tests, I found that setting SO_BINDTODEVICE to an interface had the same behavior as binding the specific IP address: no broadcast packet would be received. That is to say, your scenario can never happen by setting SO_BINDTODEVICE, why would you say it can? Did you run any tests to support your assumption? @shaunco

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request pending development Requested PR owner to improve code and waiting for the result proposal accepted Proposal has been accepted proposal Proposal for this repo
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants