-
Notifications
You must be signed in to change notification settings - Fork 175
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
[BUG] Binding to an interface on MacOS does not function correctly #378
Comments
(For reference, I did some research on this issue in #316 and coredhcp/coredhcp#52 (comment) ) I think you're right and it needs |
@Natolumin I do have a few MacOS machines a linux host, and a few RaspberryPIs lying around. |
I found some time to write a patch to try the IP_BOUND_IF option. Could you try this branch: https://github.com/Natolumin/dhcp/tree/darwin_bindtointerface ? Note while trying this I found that client4/nclient4 don't even build on darwin so yeah, our testing isn't great there Here are some instructions for using the fork if you ever need them, I hope they're correct (feel free to ignore them if you know how to do this): I think you should be able to test it with the following:
Then build your downstream application as usual. If you use modules in your downstream binary, you'll need to checkout the fork somewhere and create a go.mod file in the fork with replace github.com/insomniacslk/dhcp => ../path/to/forked/library |
@Natolumin I will work on it this weekend if time allows, sorry for the delay. |
@NonLogicalDev Were you able to give this a try? |
Hey @pmazzini / @Natolumin Appologies for admittedly long time to get this tested. I did test it though and is seems to be working with a small caveat: In this snippet: This is actually slightly wrong:
The AFAIK there is no way that I know of to tease out the domain information out of socket FD on darwin. =[ The documentation is either missing or it is just not supported via socket options. Here is Linux for reference: (https://man7.org/linux/man-pages/man7/socket.7.html)
Which only mentions SO_TYPE (which as I established does not return what we want). The good news though, if I change the code by taking out the switch statement and only leaving the IPPROTO_IP socket option (essentially hardcoding the IPV4 only operation).
Diff:
Then it WORKS!!! I tested it and my RPI I connected to a USB Ethernet adapter got its IP just fine. So that can totally be used as a starting point for a more production ready code, but we still need to figure out how to correctly apply either:
Which is going to be the hard part... Unless there is someone with Darwin Fu who knows how to tease this information out of the file descriptor. Update: Found this:
Perhaps if someone can find if that Here is the gist that details my test harness: |
@NonLogicalDev Thanks for getting back to this and testing it.
Ok, this is a starting point. Better IPv4 than nothing. If I am not mistaken the BSD
Do you have Darwin on a RPI? Also thanks @Natolumin for looking at this. Would wither of you like to submit a PR? |
@pmazzini RPI just has a basic debian linux on it. It is just nice to debug since it has a serial interface and network stack that is easier to introspect =]. It fulfills the role of a client. I am running that Sever detailed in the Gist on a Macbook. |
In regards to BSD, we are talking about the |
We could take a naive approach and attempt to set both, and see which one does not return an error. |
Here is what you get for two scenarios, when IPV4 is setup on socket:
|
After some more experimentation I concluded that: (for ipv4 case)
is enough for correct operation. In other words this is not needed:
|
Also in case of IPV6 socket this does not raise any errors
|
I can rebase and send a proper PR with these changes sometime this week. I still can't test it but now that the poc at least works it'll be quicker to test. Thanks a bunch for your research @NonLogicalDev
There's 2 paths here, we want the socket not to receive packets that are sent to other interfaces, in addition to sending them on the correct one. So to test it you need a darwin machine with 2 interfaces and sending dhcp messages to both, and check that the dhcp server only receives packets for the interface it is bound to. Afaict from the documentation, the receive path would still need
Yeah I think that would be reasonable, try both and return success if at least one succeeds |
By the way, @Natolumin where did you find all of the information about Best I found was this: (https://docs.oracle.com/cd/E86824_01/html/E54777/ip-7p.html)
But that is solaris documentation.... Seems like the IP_BOUND_IF does indeed behave differently under MacOS: https://github.com/apple/darwin-xnu/blob/main/bsd/netinet/ip_output.c?ts=4#L2471-L2486
|
Updated my gist with a better test / interface code that seems to work and is easy to test under different conditions: @Natolumin you were right about In regards to the production version of That is a bit dirty though and
Both of which are in It would be a lot less hacky to change Where the domain is either |
When picking an interface on MacOS, the server will correctly listen for packets, but when doing an offer by replying to broadcast address, the system will route that to the Gateway interface only.
This is likely due to:
I am hardly an expert in stuff this low in the stack, though from the looks of it this is just filtering the received traffic, but does nothing to direct the outbound traffic.
I have also found this, perhaps that might be the solution: 🤷♂ :
https://stackoverflow.com/a/57013928
Spent quite a few hours with Wireshark trying to figure out why the server was not sending an offer to the client, all the while not raising any alarms.
Will add a minimum viable example to illustrate the issue soon.
The text was updated successfully, but these errors were encountered: